2 * Copyright 2005-2016, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
7 #include <arch/user_debugger.h>
12 #include <driver_settings.h>
16 #include <util/AutoLock.h>
19 //#define TRACE_ARCH_USER_DEBUGGER
20 #ifdef TRACE_ARCH_USER_DEBUGGER
21 # define TRACE(x) dprintf x
26 #define B_NO_MORE_BREAKPOINTS B_BUSY
27 #define B_NO_MORE_WATCHPOINTS B_BUSY
28 #define B_BAD_WATCHPOINT_ALIGNMENT B_BAD_VALUE
29 #define B_WATCHPOINT_TYPE_NOT_SUPPORTED B_NOT_SUPPORTED
30 #define B_WATCHPOINT_LENGTH_NOT_SUPPORTED B_NOT_SUPPORTED
31 #define B_BREAKPOINT_NOT_FOUND B_NAME_NOT_FOUND
32 #define B_WATCHPOINT_NOT_FOUND B_NAME_NOT_FOUND
33 // TODO: Make those real error codes.
40 // The software breakpoint instruction (int3).
41 const uint8 kX86SoftwareBreakpoint
[1] = { 0xcc };
43 // maps breakpoint slot index to LEN_i LSB number
44 static const size_t sDR7Len
[4] = {
45 X86_DR7_LEN0_LSB
, X86_DR7_LEN1_LSB
, X86_DR7_LEN2_LSB
, X86_DR7_LEN3_LSB
48 // maps breakpoint slot index to R/W_i LSB number
49 static const size_t sDR7RW
[4] = {
50 X86_DR7_RW0_LSB
, X86_DR7_RW1_LSB
, X86_DR7_RW2_LSB
, X86_DR7_RW3_LSB
53 // maps breakpoint slot index to L_i bit number
54 static const size_t sDR7L
[4] = {
55 X86_DR7_L0
, X86_DR7_L1
, X86_DR7_L2
, X86_DR7_L3
58 // maps breakpoint slot index to G_i bit number
59 static const size_t sDR7G
[4] = {
60 X86_DR7_G0
, X86_DR7_G1
, X86_DR7_G2
, X86_DR7_G3
63 // maps breakpoint slot index to B_i bit number
64 static const size_t sDR6B
[4] = {
65 X86_DR6_B0
, X86_DR6_B1
, X86_DR6_B2
, X86_DR6_B3
68 // Enables a hack to make single stepping work under qemu. Set via kernel
70 static bool sQEmuSingleStepHack
= false;
77 get_iframe_registers(const iframe
* frame
, debug_cpu_state
* cpuState
)
79 // Get general purpose registers.
80 cpuState
->r15
= frame
->r15
;
81 cpuState
->r14
= frame
->r14
;
82 cpuState
->r13
= frame
->r13
;
83 cpuState
->r12
= frame
->r12
;
84 cpuState
->r11
= frame
->r11
;
85 cpuState
->r10
= frame
->r10
;
86 cpuState
->r9
= frame
->r9
;
87 cpuState
->r8
= frame
->r8
;
88 cpuState
->rbp
= frame
->bp
;
89 cpuState
->rsi
= frame
->si
;
90 cpuState
->rdi
= frame
->di
;
91 cpuState
->rdx
= frame
->dx
;
92 cpuState
->rcx
= frame
->cx
;
93 cpuState
->rbx
= frame
->bx
;
94 cpuState
->rax
= frame
->ax
;
95 cpuState
->vector
= frame
->vector
;
96 cpuState
->error_code
= frame
->error_code
;
97 cpuState
->rip
= frame
->ip
;
98 cpuState
->cs
= frame
->cs
;
99 cpuState
->rflags
= frame
->flags
;
100 cpuState
->rsp
= frame
->sp
;
101 cpuState
->ss
= frame
->ss
;
103 // Other segment registers are not saved or changed on interrupts, so
104 // get their value here.
106 __asm__
volatile ("movw %%ds, %0" : "=r" (seg
));
108 __asm__
volatile ("movw %%es, %0" : "=r" (seg
));
110 __asm__
volatile ("movw %%fs, %0" : "=r" (seg
));
112 __asm__
volatile ("movw %%gs, %0" : "=r" (seg
));
118 set_iframe_registers(iframe
* frame
, const debug_cpu_state
* cpuState
)
120 frame
->r15
= cpuState
->r15
;
121 frame
->r14
= cpuState
->r14
;
122 frame
->r13
= cpuState
->r13
;
123 frame
->r12
= cpuState
->r12
;
124 frame
->r11
= cpuState
->r11
;
125 frame
->r10
= cpuState
->r10
;
126 frame
->r9
= cpuState
->r9
;
127 frame
->r8
= cpuState
->r8
;
128 frame
->bp
= cpuState
->rbp
;
129 frame
->si
= cpuState
->rsi
;
130 frame
->di
= cpuState
->rdi
;
131 frame
->dx
= cpuState
->rdx
;
132 frame
->cx
= cpuState
->rcx
;
133 frame
->bx
= cpuState
->rbx
;
134 frame
->ax
= cpuState
->rax
;
135 frame
->ip
= cpuState
->rip
;
136 frame
->flags
= (frame
->flags
& ~X86_EFLAGS_USER_SETTABLE_FLAGS
)
137 | (cpuState
->rflags
& X86_EFLAGS_USER_SETTABLE_FLAGS
);
138 frame
->sp
= cpuState
->rsp
;
146 get_iframe_registers(const iframe
* frame
, debug_cpu_state
* cpuState
)
148 cpuState
->gs
= frame
->gs
;
149 cpuState
->fs
= frame
->fs
;
150 cpuState
->es
= frame
->es
;
151 cpuState
->ds
= frame
->ds
;
152 cpuState
->edi
= frame
->di
;
153 cpuState
->esi
= frame
->si
;
154 cpuState
->ebp
= frame
->bp
;
155 cpuState
->esp
= frame
->sp
;
156 cpuState
->ebx
= frame
->bx
;
157 cpuState
->edx
= frame
->orig_edx
;
158 cpuState
->ecx
= frame
->cx
;
159 cpuState
->eax
= frame
->orig_eax
;
160 cpuState
->vector
= frame
->vector
;
161 cpuState
->error_code
= frame
->error_code
;
162 cpuState
->eip
= frame
->ip
;
163 cpuState
->cs
= frame
->cs
;
164 cpuState
->eflags
= frame
->flags
;
165 cpuState
->user_esp
= frame
->user_sp
;
166 cpuState
->user_ss
= frame
->user_ss
;
171 set_iframe_registers(iframe
* frame
, const debug_cpu_state
* cpuState
)
173 // frame->gs = cpuState->gs;
174 // frame->fs = cpuState->fs;
175 // frame->es = cpuState->es;
176 // frame->ds = cpuState->ds;
177 frame
->di
= cpuState
->edi
;
178 frame
->si
= cpuState
->esi
;
179 frame
->bp
= cpuState
->ebp
;
180 // frame->esp = cpuState->esp;
181 frame
->bx
= cpuState
->ebx
;
182 frame
->dx
= cpuState
->edx
;
183 frame
->cx
= cpuState
->ecx
;
184 frame
->ax
= cpuState
->eax
;
185 // frame->vector = cpuState->vector;
186 // frame->error_code = cpuState->error_code;
187 frame
->ip
= cpuState
->eip
;
188 // frame->cs = cpuState->cs;
189 frame
->flags
= (frame
->flags
& ~X86_EFLAGS_USER_SETTABLE_FLAGS
)
190 | (cpuState
->eflags
& X86_EFLAGS_USER_SETTABLE_FLAGS
);
191 frame
->user_sp
= cpuState
->user_esp
;
192 // frame->user_ss = cpuState->user_ss;
200 get_cpu_state(Thread
* thread
, iframe
* frame
, debug_cpu_state
* cpuState
)
202 // For the floating point state to be correct the calling function must
203 // not use these registers (not even indirectly).
205 if (frame
->fpu
!= nullptr) {
206 memcpy(&cpuState
->extended_registers
, frame
->fpu
,
207 sizeof(cpuState
->extended_registers
));
209 memset(&cpuState
->extended_registers
, 0,
210 sizeof(cpuState
->extended_registers
));
213 Thread
* thisThread
= thread_get_current_thread();
215 if (thread
== thisThread
) {
216 // Since fxsave requires 16-byte alignment and this isn't guaranteed
217 // for the passed buffer, we use our thread's fpu_state field as
218 // temporary buffer. We need to disable interrupts to make use of
220 Thread
* thread
= thread_get_current_thread();
221 InterruptsLocker locker
;
222 x86_fxsave(thread
->arch_info
.fpu_state
);
223 // unlike fnsave, fxsave doesn't reinit the FPU state
225 memcpy(&cpuState
->extended_registers
, thread
->arch_info
.fpu_state
,
226 sizeof(cpuState
->extended_registers
));
228 if (thread
== thisThread
) {
229 x86_fnsave(&cpuState
->extended_registers
);
230 // fnsave reinits the FPU state after saving, so we need to
232 x86_frstor(&cpuState
->extended_registers
);
234 memcpy(&cpuState
->extended_registers
, thread
->arch_info
.fpu_state
,
235 sizeof(cpuState
->extended_registers
));
237 // TODO: Convert to fxsave format!
240 get_iframe_registers(frame
, cpuState
);
245 install_breakpoints(const arch_team_debug_info
& teamInfo
)
248 asm("mov %0, %%dr0" : : "r"(teamInfo
.breakpoints
[0].address
));
249 asm("mov %0, %%dr1" : : "r"(teamInfo
.breakpoints
[1].address
));
250 asm("mov %0, %%dr2" : : "r"(teamInfo
.breakpoints
[2].address
));
251 asm("mov %0, %%dr3" : : "r"(teamInfo
.breakpoints
[3].address
));
253 // enable breakpoints
254 asm("mov %0, %%dr7" : : "r"(teamInfo
.dr7
));
259 disable_breakpoints()
261 asm("mov %0, %%dr7" : : "r"((size_t)X86_BREAKPOINTS_DISABLED_DR7
));
265 /*! Sets a break-/watchpoint in the given team info.
266 Interrupts must be disabled and the team debug info lock be held.
268 static inline status_t
269 set_breakpoint(arch_team_debug_info
& info
, void* address
, size_t type
,
270 size_t length
, bool setGlobalFlag
)
272 // check, if there is already a breakpoint at that address
273 bool alreadySet
= false;
274 for (int32 i
= 0; i
< X86_BREAKPOINT_COUNT
; i
++) {
275 if (info
.breakpoints
[i
].address
== address
276 && info
.breakpoints
[i
].type
== type
) {
285 for (int32 i
= 0; i
< X86_BREAKPOINT_COUNT
; i
++) {
286 if (!info
.breakpoints
[i
].address
) {
292 // init the breakpoint
294 info
.breakpoints
[slot
].address
= address
;
295 info
.breakpoints
[slot
].type
= type
;
296 info
.breakpoints
[slot
].length
= length
;
298 info
.dr7
|= (length
<< sDR7Len
[slot
])
299 | (type
<< sDR7RW
[slot
])
300 | (1 << sDR7L
[slot
]);
302 info
.dr7
|= (1 << sDR7G
[slot
]);
304 if (type
== X86_INSTRUCTION_BREAKPOINT
)
305 return B_NO_MORE_BREAKPOINTS
;
307 return B_NO_MORE_WATCHPOINTS
;
315 /*! Clears a break-/watchpoint in the given team info.
316 Interrupts must be disabled and the team debug info lock be held.
318 static inline status_t
319 clear_breakpoint(arch_team_debug_info
& info
, void* address
, bool watchpoint
)
321 // find the breakpoint
323 for (int32 i
= 0; i
< X86_BREAKPOINT_COUNT
; i
++) {
324 if (info
.breakpoints
[i
].address
== address
326 != (info
.breakpoints
[i
].type
== X86_INSTRUCTION_BREAKPOINT
))) {
332 // clear the breakpoint
334 info
.breakpoints
[slot
].address
= NULL
;
336 info
.dr7
&= ~((0x3 << sDR7Len
[slot
])
337 | (0x3 << sDR7RW
[slot
])
339 | (1 << sDR7G
[slot
]));
342 return B_WATCHPOINT_NOT_FOUND
;
344 return B_BREAKPOINT_NOT_FOUND
;
352 set_breakpoint(void* address
, size_t type
, size_t length
)
357 Thread
* thread
= thread_get_current_thread();
359 cpu_status state
= disable_interrupts();
360 GRAB_TEAM_DEBUG_INFO_LOCK(thread
->team
->debug_info
);
362 status_t error
= set_breakpoint(thread
->team
->debug_info
.arch_info
, address
,
363 type
, length
, false);
365 RELEASE_TEAM_DEBUG_INFO_LOCK(thread
->team
->debug_info
);
366 restore_interrupts(state
);
373 clear_breakpoint(void* address
, bool watchpoint
)
378 Thread
* thread
= thread_get_current_thread();
380 cpu_status state
= disable_interrupts();
381 GRAB_TEAM_DEBUG_INFO_LOCK(thread
->team
->debug_info
);
383 status_t error
= clear_breakpoint(thread
->team
->debug_info
.arch_info
,
384 address
, watchpoint
);
386 RELEASE_TEAM_DEBUG_INFO_LOCK(thread
->team
->debug_info
);
387 restore_interrupts(state
);
393 #if KERNEL_BREAKPOINTS
397 install_breakpoints_per_cpu(void* /*cookie*/, int cpu
)
399 Team
* kernelTeam
= team_get_kernel_team();
401 GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam
->debug_info
);
403 install_breakpoints(kernelTeam
->debug_info
.arch_info
);
405 RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam
->debug_info
);
410 set_kernel_breakpoint(void* address
, size_t type
, size_t length
)
415 Team
* kernelTeam
= team_get_kernel_team();
417 cpu_status state
= disable_interrupts();
418 GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam
->debug_info
);
420 status_t error
= set_breakpoint(kernelTeam
->debug_info
.arch_info
, address
,
423 RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam
->debug_info
);
425 call_all_cpus(install_breakpoints_per_cpu
, NULL
);
427 restore_interrupts(state
);
434 clear_kernel_breakpoint(void* address
, bool watchpoint
)
439 Team
* kernelTeam
= team_get_kernel_team();
441 cpu_status state
= disable_interrupts();
442 GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam
->debug_info
);
444 status_t error
= clear_breakpoint(kernelTeam
->debug_info
.arch_info
,
445 address
, watchpoint
);
447 RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam
->debug_info
);
449 call_all_cpus(install_breakpoints_per_cpu
, NULL
);
451 restore_interrupts(state
);
456 #endif // KERNEL_BREAKPOINTS
459 static inline status_t
460 check_watch_point_parameters(void* address
, uint32 type
, int32 length
,
461 size_t& archType
, size_t& archLength
)
465 case B_DATA_WRITE_WATCHPOINT
:
466 archType
= X86_DATA_WRITE_BREAKPOINT
;
468 case B_DATA_READ_WRITE_WATCHPOINT
:
469 archType
= X86_DATA_READ_WRITE_BREAKPOINT
;
471 case B_DATA_READ_WATCHPOINT
:
473 return B_WATCHPOINT_TYPE_NOT_SUPPORTED
;
477 // check length and alignment
480 archLength
= X86_BREAKPOINT_LENGTH_1
;
483 if ((addr_t
)address
& 0x1)
484 return B_BAD_WATCHPOINT_ALIGNMENT
;
485 archLength
= X86_BREAKPOINT_LENGTH_2
;
488 if ((addr_t
)address
& 0x3)
489 return B_BAD_WATCHPOINT_ALIGNMENT
;
490 archLength
= X86_BREAKPOINT_LENGTH_4
;
493 return B_WATCHPOINT_LENGTH_NOT_SUPPORTED
;
500 // #pragma mark - kernel debugger commands
503 #if KERNEL_BREAKPOINTS
506 debugger_breakpoints(int argc
, char** argv
)
508 Team
* kernelTeam
= team_get_kernel_team();
509 arch_team_debug_info
& info
= kernelTeam
->debug_info
.arch_info
;
511 for (int32 i
= 0; i
< X86_BREAKPOINT_COUNT
; i
++) {
512 kprintf("breakpoint[%" B_PRId32
"] ", i
);
514 if (info
.breakpoints
[i
].address
!= NULL
) {
515 kprintf("%p ", info
.breakpoints
[i
].address
);
516 switch (info
.breakpoints
[i
].type
) {
517 case X86_INSTRUCTION_BREAKPOINT
:
518 kprintf("instruction");
520 case X86_IO_READ_WRITE_BREAKPOINT
:
521 kprintf("io read/write");
523 case X86_DATA_WRITE_BREAKPOINT
:
524 kprintf("data write");
526 case X86_DATA_READ_WRITE_BREAKPOINT
:
527 kprintf("data read/write");
532 switch (info
.breakpoints
[i
].length
) {
533 case X86_BREAKPOINT_LENGTH_1
:
536 case X86_BREAKPOINT_LENGTH_2
:
539 case X86_BREAKPOINT_LENGTH_4
:
544 if (info
.breakpoints
[i
].type
!= X86_INSTRUCTION_BREAKPOINT
)
545 kprintf(" %d byte%s", length
, (length
> 1 ? "s" : ""));
557 debugger_breakpoint(int argc
, char** argv
)
561 if (argc
< 2 || argc
> 3)
562 return print_debugger_command_usage(argv
[0]);
564 addr_t address
= strtoul(argv
[1], NULL
, 0);
566 return print_debugger_command_usage(argv
[0]);
570 if (strcmp(argv
[2], "clear") == 0)
573 return print_debugger_command_usage(argv
[0]);
576 // set/clear breakpoint
578 arch_team_debug_info
& info
= team_get_kernel_team()->debug_info
.arch_info
;
583 error
= clear_breakpoint(info
, (void*)address
, false);
585 error
= set_breakpoint(info
, (void*)address
, X86_INSTRUCTION_BREAKPOINT
,
586 X86_BREAKPOINT_LENGTH_1
, true);
590 call_all_cpus_sync(install_breakpoints_per_cpu
, NULL
);
592 kprintf("Failed to install breakpoint: %s\n", strerror(error
));
599 debugger_watchpoint(int argc
, char** argv
)
603 if (argc
< 2 || argc
> 4)
604 return print_debugger_command_usage(argv
[0]);
606 addr_t address
= strtoul(argv
[1], NULL
, 0);
608 return print_debugger_command_usage(argv
[0]);
611 bool readWrite
= false;
615 if (strcmp(argv
[argi
], "clear") == 0) {
618 } else if (strcmp(argv
[argi
], "rw") == 0) {
623 if (!clear
&& argi
< argc
)
624 length
= strtoul(argv
[argi
++], NULL
, 0);
626 if (length
== 0 || argi
< argc
)
627 return print_debugger_command_usage(argv
[0]);
630 // set/clear breakpoint
632 arch_team_debug_info
& info
= team_get_kernel_team()->debug_info
.arch_info
;
637 error
= clear_breakpoint(info
, (void*)address
, true);
639 uint32 type
= readWrite
? B_DATA_READ_WRITE_WATCHPOINT
640 : B_DATA_WRITE_WATCHPOINT
;
642 size_t archType
, archLength
;
643 error
= check_watch_point_parameters((void*)address
, type
, length
,
644 archType
, archLength
);
647 error
= set_breakpoint(info
, (void*)address
, archType
, archLength
,
653 call_all_cpus_sync(install_breakpoints_per_cpu
, NULL
);
655 kprintf("Failed to install breakpoint: %s\n", strerror(error
));
662 debugger_single_step(int argc
, char** argv
)
664 // TODO: Since we need an iframe, this doesn't work when KDL wasn't entered
667 iframe
* frame
= x86_get_current_iframe();
669 kprintf("Failed to get the current iframe!\n");
673 frame
->flags
|= (1 << X86_EFLAGS_TF
);
675 return B_KDEBUG_QUIT
;
679 #endif // KERNEL_BREAKPOINTS
682 // #pragma mark - in-kernel public interface
686 arch_clear_team_debug_info(arch_team_debug_info
* info
)
688 for (int32 i
= 0; i
< X86_BREAKPOINT_COUNT
; i
++)
689 info
->breakpoints
[i
].address
= NULL
;
691 info
->dr7
= X86_BREAKPOINTS_DISABLED_DR7
;
696 arch_destroy_team_debug_info(arch_team_debug_info
* info
)
698 arch_clear_team_debug_info(info
);
703 arch_clear_thread_debug_info(arch_thread_debug_info
* info
)
710 arch_destroy_thread_debug_info(arch_thread_debug_info
* info
)
712 arch_clear_thread_debug_info(info
);
717 arch_update_thread_single_step()
719 if (iframe
* frame
= x86_get_user_iframe()) {
720 Thread
* thread
= thread_get_current_thread();
722 // set/clear TF in EFLAGS depending on whether single stepping is
724 if (thread
->debug_info
.flags
& B_THREAD_DEBUG_SINGLE_STEP
)
725 frame
->flags
|= (1 << X86_EFLAGS_TF
);
727 frame
->flags
&= ~(1 << X86_EFLAGS_TF
);
733 arch_set_debug_cpu_state(const debug_cpu_state
* cpuState
)
735 if (iframe
* frame
= x86_get_user_iframe()) {
736 // For the floating point state to be correct the calling function must
737 // not use these registers (not even indirectly).
739 Thread
* thread
= thread_get_current_thread();
740 memcpy(thread
->arch_info
.fpu_state
, &cpuState
->extended_registers
,
741 sizeof(cpuState
->extended_registers
));
742 frame
->fpu
= &thread
->arch_info
.fpu_state
;
745 // Since fxrstor requires 16-byte alignment and this isn't
746 // guaranteed passed buffer, we use our thread's fpu_state field as
747 // temporary buffer. We need to disable interrupts to make use of
749 Thread
* thread
= thread_get_current_thread();
750 InterruptsLocker locker
;
751 memcpy(thread
->arch_info
.fpu_state
, &cpuState
->extended_registers
,
752 sizeof(cpuState
->extended_registers
));
753 x86_fxrstor(thread
->arch_info
.fpu_state
);
755 // TODO: Implement! We need to convert the format first.
756 // x86_frstor(&cpuState->extended_registers);
759 set_iframe_registers(frame
, cpuState
);
765 arch_get_debug_cpu_state(debug_cpu_state
* cpuState
)
767 if (iframe
* frame
= x86_get_user_iframe())
768 get_cpu_state(thread_get_current_thread(), frame
, cpuState
);
772 /*! \brief Retrieves the CPU state for the given thread.
773 The thread must not be running and the thread's scheduler spinlock must be
775 \param thread The thread whose CPU state to retrieve.
776 \param cpuState Pointer to pre-allocated storage for the CPU state.
777 \return \c B_OK, if everything goes fine, another error code, if the CPU
778 state could not be retrieved.
781 arch_get_thread_debug_cpu_state(Thread
* thread
, debug_cpu_state
* cpuState
)
783 iframe
* frame
= x86_get_thread_user_iframe(thread
);
787 get_cpu_state(thread
, frame
, cpuState
);
793 arch_set_breakpoint(void* address
)
795 return set_breakpoint(address
, X86_INSTRUCTION_BREAKPOINT
,
796 X86_BREAKPOINT_LENGTH_1
);
801 arch_clear_breakpoint(void* address
)
803 return clear_breakpoint(address
, false);
808 arch_set_watchpoint(void* address
, uint32 type
, int32 length
)
810 size_t archType
, archLength
;
811 status_t error
= check_watch_point_parameters(address
, type
, length
,
812 archType
, archLength
);
816 return set_breakpoint(address
, archType
, archLength
);
821 arch_clear_watchpoint(void* address
)
823 return clear_breakpoint(address
, true);
828 arch_has_breakpoints(arch_team_debug_info
* info
)
830 // Reading info->dr7 is atomically, so we don't need to lock. The caller
831 // has to ensure, that the info doesn't go away.
832 return (info
->dr7
!= X86_BREAKPOINTS_DISABLED_DR7
);
836 #if KERNEL_BREAKPOINTS
839 arch_set_kernel_breakpoint(void* address
)
841 status_t error
= set_kernel_breakpoint(address
, X86_INSTRUCTION_BREAKPOINT
,
842 X86_BREAKPOINT_LENGTH_1
);
845 panic("arch_set_kernel_breakpoint() failed to set breakpoint: %s",
854 arch_clear_kernel_breakpoint(void* address
)
856 status_t error
= clear_kernel_breakpoint(address
, false);
859 panic("arch_clear_kernel_breakpoint() failed to clear breakpoint: %s",
868 arch_set_kernel_watchpoint(void* address
, uint32 type
, int32 length
)
870 size_t archType
, archLength
;
871 status_t error
= check_watch_point_parameters(address
, type
, length
,
872 archType
, archLength
);
875 error
= set_kernel_breakpoint(address
, archType
, archLength
);
878 panic("arch_set_kernel_watchpoint() failed to set watchpoint: %s",
887 arch_clear_kernel_watchpoint(void* address
)
889 status_t error
= clear_kernel_breakpoint(address
, true);
892 panic("arch_clear_kernel_watchpoint() failed to clear watchpoint: %s",
899 #endif // KERNEL_BREAKPOINTS
902 // #pragma mark - x86 implementation interface
906 * Interrupts are disabled. \a frame is unused, i.e. can be \c NULL.
909 x86_init_user_debug_at_kernel_exit(iframe
* frame
)
911 Thread
* thread
= thread_get_current_thread();
913 if (!(thread
->flags
& THREAD_FLAGS_BREAKPOINTS_DEFINED
))
916 // disable kernel breakpoints
917 disable_breakpoints();
919 // install the user breakpoints
920 GRAB_TEAM_DEBUG_INFO_LOCK(thread
->team
->debug_info
);
922 arch_team_debug_info
&teamInfo
= thread
->team
->debug_info
.arch_info
;
924 install_breakpoints(teamInfo
);
926 atomic_or(&thread
->flags
, THREAD_FLAGS_BREAKPOINTS_INSTALLED
);
928 RELEASE_TEAM_DEBUG_INFO_LOCK(thread
->team
->debug_info
);
933 * Interrupts are disabled.
936 x86_exit_user_debug_at_kernel_entry()
938 Thread
* thread
= thread_get_current_thread();
940 // We need to save the current values of dr6 and dr7 in the CPU structure,
941 // since in case of a debug exception we might overwrite them before
942 // x86_handle_debug_exception() is called. Debug exceptions occur when
943 // hitting a hardware break/watchpoint or when single-stepping.
944 asm("mov %%dr6, %0" : "=r"(thread
->cpu
->arch
.dr6
));
945 asm("mov %%dr7, %0" : "=r"(thread
->cpu
->arch
.dr7
));
947 // The remainder needs only be done, when user breakpoints are installed.
948 if (!(thread
->flags
& THREAD_FLAGS_BREAKPOINTS_INSTALLED
))
951 // disable user breakpoints
952 disable_breakpoints();
954 // install kernel breakpoints
955 Team
* kernelTeam
= team_get_kernel_team();
957 GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam
->debug_info
);
959 install_breakpoints(kernelTeam
->debug_info
.arch_info
);
961 atomic_and(&thread
->flags
, ~THREAD_FLAGS_BREAKPOINTS_INSTALLED
);
963 RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam
->debug_info
);
968 * Interrupts are disabled and will possibly be enabled by the function.
971 x86_handle_debug_exception(iframe
* frame
)
973 Thread
* thread
= thread_get_current_thread();
975 // Get dr6 and dr7. If the given iframe is a userland frame, the exception
976 // obviously occurred in userland. In that case
977 // x86_exit_user_debug_at_kernel_entry() has already been invoked and dr6
978 // and dr7 are stored in the cpu info. Otherwise we need to fetch the
979 // current values from the registers.
982 if (IFRAME_IS_USER(frame
)) {
983 dr6
= thread
->cpu
->arch
.dr6
;
984 dr7
= thread
->cpu
->arch
.dr7
;
986 asm("mov %%dr6, %0" : "=r"(dr6
));
987 asm("mov %%dr7, %0" : "=r"(dr7
));
990 TRACE(("x86_handle_debug_exception(): DR6: %lx, DR7: %lx\n", dr6
, dr7
));
992 // check, which exception condition applies
993 if (dr6
& X86_DR6_BREAKPOINT_MASK
) {
996 // check which breakpoint was taken
997 bool watchpoint
= true;
998 for (int32 i
= 0; i
< X86_BREAKPOINT_COUNT
; i
++) {
999 if (dr6
& (1 << sDR6B
[i
])) {
1000 size_t type
= (dr7
>> sDR7RW
[i
]) & 0x3;
1001 if (type
== X86_INSTRUCTION_BREAKPOINT
)
1006 if (IFRAME_IS_USER(frame
)) {
1007 // enable interrupts and notify the debugger
1008 enable_interrupts();
1011 user_debug_watchpoint_hit();
1013 user_debug_breakpoint_hit(false);
1015 panic("hit kernel %spoint: dr6: 0x%lx, dr7: 0x%lx",
1016 watchpoint
? "watch" : "break", dr6
, dr7
);
1018 } else if (dr6
& (1 << X86_DR6_BD
)) {
1019 // general detect exception
1020 // Occurs only, if GD in DR7 is set (which we don't do) and someone
1021 // tries to write to the debug registers.
1022 if (IFRAME_IS_USER(frame
)) {
1023 dprintf("x86_handle_debug_exception(): ignoring spurious general "
1024 "detect exception\n");
1026 enable_interrupts();
1028 panic("spurious general detect exception in kernel mode");
1029 } else if ((dr6
& (1 << X86_DR6_BS
)) || sQEmuSingleStepHack
) {
1032 if (IFRAME_IS_USER(frame
)) {
1033 // enable interrupts and notify the debugger
1034 enable_interrupts();
1036 user_debug_single_stepped();
1038 // Disable single-stepping -- the next "step" command will re-enable
1039 // it, but we don't want it when continuing otherwise.
1040 frame
->flags
&= ~(1 << X86_EFLAGS_TF
);
1042 // Determine whether the exception occurred at a syscall/trap
1043 // kernel entry or whether this is genuine kernel single-stepping.
1044 bool inKernel
= true;
1045 if (thread
->team
!= team_get_kernel_team()
1046 && x86_get_user_iframe() == NULL
) {
1047 // TODO: This is not yet fully correct, since a newly created
1048 // thread that hasn't entered userland yet also has this
1054 panic("kernel single step");
1056 // The thread is a userland thread and it just entered the
1057 // kernel when the single-step exception occurred. This happens
1058 // e.g. when sysenter is called with single-stepping enabled.
1059 // We need to ignore the exception now and send a single-step
1060 // notification later, when the thread wants to return from the
1062 InterruptsSpinLocker
threadDebugInfoLocker(
1063 thread
->debug_info
.lock
);
1065 // Check whether the team is still being debugged and set
1066 // the B_THREAD_DEBUG_NOTIFY_SINGLE_STEP and
1067 // B_THREAD_DEBUG_STOP flags, so that the thread will be
1068 // stopped when it is going to leave the kernel and notify the
1069 // debugger about the single-step event.
1070 int32 teamDebugFlags
1071 = atomic_get(&thread
->team
->debug_info
.flags
);
1072 if (teamDebugFlags
& B_TEAM_DEBUG_DEBUGGER_INSTALLED
) {
1073 atomic_or(&thread
->debug_info
.flags
,
1074 B_THREAD_DEBUG_NOTIFY_SINGLE_STEP
1075 | B_THREAD_DEBUG_STOP
);
1077 // also set the respective thread flag
1078 atomic_or(&thread
->flags
, THREAD_FLAGS_DEBUG_THREAD
);
1082 } else if (dr6
& (1 << X86_DR6_BT
)) {
1084 // Occurs only, if T in EFLAGS is set (which we don't do).
1085 if (IFRAME_IS_USER(frame
)) {
1086 dprintf("x86_handle_debug_exception(): ignoring spurious task switch "
1089 enable_interrupts();
1091 panic("spurious task switch exception in kernel mode");
1093 if (IFRAME_IS_USER(frame
)) {
1094 TRACE(("x86_handle_debug_exception(): ignoring spurious debug "
1095 "exception (no condition recognized)\n"));
1097 enable_interrupts();
1099 panic("spurious debug exception in kernel mode (no condition "
1107 * Interrupts are disabled and will possibly be enabled by the function.
1110 x86_handle_breakpoint_exception(iframe
* frame
)
1112 TRACE(("x86_handle_breakpoint_exception()\n"));
1114 // reset eip to the int3 instruction
1117 if (!IFRAME_IS_USER(frame
)) {
1118 panic("breakpoint exception in kernel mode");
1122 enable_interrupts();
1124 user_debug_breakpoint_hit(true);
1129 x86_init_user_debug()
1131 // get debug settings
1132 if (void* handle
= load_driver_settings("kernel")) {
1133 sQEmuSingleStepHack
= get_driver_boolean_parameter(handle
,
1134 "qemu_single_step_hack", false, false);;
1136 unload_driver_settings(handle
);
1139 #if KERNEL_BREAKPOINTS
1140 // install debugger commands
1141 add_debugger_command_etc("breakpoints", &debugger_breakpoints
,
1142 "Lists current break-/watchpoints",
1144 "Lists the current kernel break-/watchpoints.\n", 0);
1145 add_debugger_command_alias("watchpoints", "breakpoints", NULL
);
1146 add_debugger_command_etc("breakpoint", &debugger_breakpoint
,
1147 "Set/clears a breakpoint",
1148 "<address> [ clear ]\n"
1149 "Sets respectively clears the breakpoint at address <address>.\n", 0);
1150 add_debugger_command_etc("watchpoint", &debugger_watchpoint
,
1151 "Set/clears a watchpoint",
1152 "<address> <address> ( [ rw ] [ <size> ] | clear )\n"
1153 "Sets respectively clears the watchpoint at address <address>.\n"
1154 "If \"rw\" is given the new watchpoint is a read/write watchpoint\n"
1155 "otherwise a write watchpoint only.\n", 0);
1156 add_debugger_command_etc("step", &debugger_single_step
,
1157 "Single-steps to the next instruction",
1159 "Single-steps to the next instruction.\n", 0);