2 Processor specific parts of the GDB stub
4 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <GdbStubInternal.h>
13 // Array of exception types that need to be hooked by the debugger
15 EFI_EXCEPTION_TYPE_ENTRY gExceptionType
[] = {
16 { EXCEPT_X64_DIVIDE_ERROR
, GDB_SIGFPE
},
17 { EXCEPT_X64_DEBUG
, GDB_SIGTRAP
},
18 { EXCEPT_X64_NMI
, GDB_SIGEMT
},
19 { EXCEPT_X64_BREAKPOINT
, GDB_SIGTRAP
},
20 { EXCEPT_X64_OVERFLOW
, GDB_SIGSEGV
},
21 { EXCEPT_X64_BOUND
, GDB_SIGSEGV
},
22 { EXCEPT_X64_INVALID_OPCODE
, GDB_SIGILL
},
23 { EXCEPT_X64_DOUBLE_FAULT
, GDB_SIGEMT
},
24 { EXCEPT_X64_STACK_FAULT
, GDB_SIGSEGV
},
25 { EXCEPT_X64_GP_FAULT
, GDB_SIGSEGV
},
26 { EXCEPT_X64_PAGE_FAULT
, GDB_SIGSEGV
},
27 { EXCEPT_X64_FP_ERROR
, GDB_SIGEMT
},
28 { EXCEPT_X64_ALIGNMENT_CHECK
, GDB_SIGEMT
},
29 { EXCEPT_X64_MACHINE_CHECK
, GDB_SIGEMT
}
32 // The offsets of registers SystemContextX64.
33 // The fields in the array are in the gdb ordering.
34 // HAVE TO DOUBLE-CHECK THE ORDER of the 24 regs
36 UINTN gRegisterOffsets
[] = {
37 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Rax
),
38 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Rcx
),
39 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Rdx
),
40 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Rbx
),
41 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Rsp
),
42 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Rbp
),
43 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Rsi
),
44 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Rdi
),
45 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Rip
),
46 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Rflags
),
47 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Cs
),
48 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Ss
),
49 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Ds
),
50 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Es
),
51 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Fs
),
52 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, Gs
),
53 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, R8
),
54 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, R9
),
55 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, R10
),
56 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, R11
),
57 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, R12
),
58 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, R13
),
59 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, R14
),
60 OFFSET_OF (EFI_SYSTEM_CONTEXT_X64
, R15
)
64 Return the number of entries in the gExceptionType[]
66 @retval UINTN, the number of entries in the gExceptionType[] array.
73 return sizeof (gExceptionType
)/sizeof (EFI_EXCEPTION_TYPE_ENTRY
);
77 Return the number of entries in the gRegisters[]
79 @retval UINTN, the number of entries (registers) in the gRegisters[] array.
86 return sizeof (gRegisterOffsets
)/sizeof (UINTN
);
90 Check to see if the ISA is supported.
91 ISA = Instruction Set Architecture
93 @retval TRUE if Isa is supported
97 IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
100 return (BOOLEAN
)(Isa
== IsaX64
);
104 This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
105 It is, by default, set to find the register pointer of the X64 member
106 @param SystemContext Register content at time of the exception
107 @param RegNumber The register to which we want to find a pointer
108 @retval the pointer to the RegNumber-th pointer
111 FindPointerToRegister (
112 IN EFI_SYSTEM_CONTEXT SystemContext
,
118 TempPtr
= ((UINT8
*)SystemContext
.SystemContextX64
) + gRegisterOffsets
[RegNumber
];
119 return (UINTN
*)TempPtr
;
123 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
124 @param SystemContext Register content at time of the exception
125 @param RegNumber the number of the register that we want to read
126 @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
127 @retval the pointer to the next character of the output buffer that is available to be written on.
131 IN EFI_SYSTEM_CONTEXT SystemContext
,
139 while (RegSize
< 64) {
140 *OutBufPtr
++ = mHexToStr
[((*FindPointerToRegister (SystemContext
, RegNumber
) >> (RegSize
+4)) & 0xf)];
141 *OutBufPtr
++ = mHexToStr
[((*FindPointerToRegister (SystemContext
, RegNumber
) >> RegSize
) & 0xf)];
142 RegSize
= RegSize
+ 8;
149 Reads the n-th register's value into an output buffer and sends it as a packet
150 @param SystemContext Register content at time of the exception
151 @param InBuffer Pointer to the input buffer received from gdb server
155 IN EFI_SYSTEM_CONTEXT SystemContext
,
160 CHAR8 OutBuffer
[17]; // 1 reg=16 hex chars, and the end '\0' (escape seq)
161 CHAR8
*OutBufPtr
; // pointer to the output buffer
163 RegNumber
= AsciiStrHexToUintn (&InBuffer
[1]);
165 if ((RegNumber
< 0) || (RegNumber
>= MaxRegisterCount ())) {
166 SendError (GDB_EINVALIDREGNUM
);
170 OutBufPtr
= OutBuffer
;
171 OutBufPtr
= BasicReadRegister (SystemContext
, RegNumber
, OutBufPtr
);
173 *OutBufPtr
= '\0'; // the end of the buffer
174 SendPacket (OutBuffer
);
178 Reads the general registers into an output buffer and sends it as a packet
180 @param SystemContext Register content at time of the exception
184 ReadGeneralRegisters (
185 IN EFI_SYSTEM_CONTEXT SystemContext
189 CHAR8 OutBuffer
[385]; // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
190 CHAR8
*OutBufPtr
; // pointer to the output buffer
192 OutBufPtr
= OutBuffer
;
193 for (i
= 0; i
< MaxRegisterCount (); i
++) {
194 // there are only 24 registers to read
195 OutBufPtr
= BasicReadRegister (SystemContext
, i
, OutBufPtr
);
198 *OutBufPtr
= '\0'; // the end of the buffer
199 SendPacket (OutBuffer
);
203 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
205 @param SystemContext Register content at time of the exception
206 @param RegNumber the number of the register that we want to write
207 @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
208 @retval the pointer to the next character of the input buffer that can be used
212 IN EFI_SYSTEM_CONTEXT SystemContext
,
218 UINTN TempValue
; // the value transferred from a hex char
219 UINT64 NewValue
; // the new value of the RegNumber-th Register
223 while (RegSize
< 64) {
224 TempValue
= HexCharToInt (*InBufPtr
++);
227 SendError (GDB_EBADMEMDATA
);
231 NewValue
+= (TempValue
<< (RegSize
+4));
232 TempValue
= HexCharToInt (*InBufPtr
++);
235 SendError (GDB_EBADMEMDATA
);
239 NewValue
+= (TempValue
<< RegSize
);
240 RegSize
= RegSize
+ 8;
243 *(FindPointerToRegister (SystemContext
, RegNumber
)) = NewValue
;
248 Writes the new value of n-th register received into the input buffer to the n-th register
250 @param SystemContext Register content at time of the exception
251 @param InBuffer Pointer to the input buffer received from gdb server
256 IN EFI_SYSTEM_CONTEXT SystemContext
,
261 CHAR8 RegNumBuffer
[MAX_REG_NUM_BUF_SIZE
]; // put the 'n..' part of the message into this array
263 CHAR8
*InBufPtr
; // pointer to the input buffer
265 // find the register number to write
266 InBufPtr
= &InBuffer
[1];
267 RegNumBufPtr
= RegNumBuffer
;
268 while (*InBufPtr
!= '=') {
269 *RegNumBufPtr
++ = *InBufPtr
++;
272 *RegNumBufPtr
= '\0';
273 RegNumber
= AsciiStrHexToUintn (RegNumBuffer
);
275 // check if this is a valid Register Number
276 if ((RegNumber
< 0) || (RegNumber
>= MaxRegisterCount ())) {
277 SendError (GDB_EINVALIDREGNUM
);
281 InBufPtr
++; // skips the '=' character
282 BasicWriteRegister (SystemContext
, RegNumber
, InBufPtr
);
287 Writes the new values received into the input buffer to the general registers
289 @param SystemContext Register content at time of the exception
290 @param InBuffer Pointer to the input buffer received from gdb server
294 WriteGeneralRegisters (
295 IN EFI_SYSTEM_CONTEXT SystemContext
,
300 CHAR8
*InBufPtr
; /// pointer to the input buffer
302 // check to see if the buffer is the right size which is
303 // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 385
304 if (AsciiStrLen (InBuffer
) != 385) {
305 // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
306 // Bad message. Message is not the right length
307 SendError (GDB_EBADBUFSIZE
);
311 InBufPtr
= &InBuffer
[1];
313 // Read the new values for the registers from the input buffer to an array, NewValueArray.
314 // The values in the array are in the gdb ordering
315 for (i
= 0; i
< MaxRegisterCount (); i
++) {
316 // there are only 16 registers to write
317 InBufPtr
= BasicWriteRegister (SystemContext
, i
, InBufPtr
);
324 Insert Single Step in the SystemContext
326 @param SystemContext Register content at time of the exception
330 IN EFI_SYSTEM_CONTEXT SystemContext
333 SystemContext
.SystemContextX64
->Rflags
|= TF_BIT
; // Setting the TF bit.
337 Remove Single Step in the SystemContext
339 @param SystemContext Register content at time of the exception
343 IN EFI_SYSTEM_CONTEXT SystemContext
346 SystemContext
.SystemContextX64
->Rflags
&= ~TF_BIT
; // clearing the TF bit.
350 Continue. addr is Address to resume. If addr is omitted, resume at current
353 @param SystemContext Register content at time of the exception
358 IN EFI_SYSTEM_CONTEXT SystemContext
,
362 if (PacketData
[1] != '\0') {
363 SystemContext
.SystemContextX64
->Rip
= AsciiStrHexToUintn (&PacketData
[1]);
368 Single step. addr is the Address at which to resume. If addr is omitted, resume
371 @param SystemContext Register content at time of the exception
376 IN EFI_SYSTEM_CONTEXT SystemContext
,
380 if (PacketData
[1] != '\0') {
381 SystemContext
.SystemContextX64
->Rip
= AsciiStrHexToUintn (&PacketData
[1]);
384 AddSingleStep (SystemContext
);
388 Returns breakpoint data address from DR0-DR3 based on the input breakpoint
391 @param SystemContext Register content at time of the exception
392 @param BreakpointNumber Breakpoint number
394 @retval Address Data address from DR0-DR3 based on the
399 GetBreakpointDataAddress (
400 IN EFI_SYSTEM_CONTEXT SystemContext
,
401 IN UINTN BreakpointNumber
406 if (BreakpointNumber
== 1) {
407 Address
= SystemContext
.SystemContextIa32
->Dr0
;
408 } else if (BreakpointNumber
== 2) {
409 Address
= SystemContext
.SystemContextIa32
->Dr1
;
410 } else if (BreakpointNumber
== 3) {
411 Address
= SystemContext
.SystemContextIa32
->Dr2
;
412 } else if (BreakpointNumber
== 4) {
413 Address
= SystemContext
.SystemContextIa32
->Dr3
;
422 Returns currently detected breakpoint value based on the register
424 If no breakpoint is detected then it returns 0.
426 @param SystemContext Register content at time of the exception
428 @retval {1-4} Currently detected breakpoint value
429 @retval 0 No breakpoint detected.
433 GetBreakpointDetected (
434 IN EFI_SYSTEM_CONTEXT SystemContext
438 UINTN BreakpointNumber
;
440 Dr6
.UintN
= SystemContext
.SystemContextIa32
->Dr6
;
442 if (Dr6
.Bits
.B0
== 1) {
443 BreakpointNumber
= 1;
444 } else if (Dr6
.Bits
.B1
== 1) {
445 BreakpointNumber
= 2;
446 } else if (Dr6
.Bits
.B2
== 1) {
447 BreakpointNumber
= 3;
448 } else if (Dr6
.Bits
.B3
== 1) {
449 BreakpointNumber
= 4;
451 BreakpointNumber
= 0; // No breakpoint detected
454 return BreakpointNumber
;
458 Returns Breakpoint type (InstructionExecution, DataWrite, DataRead
459 or DataReadWrite) based on the Breakpoint number
461 @param SystemContext Register content at time of the exception
462 @param BreakpointNumber Breakpoint number
464 @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn
465 field. For unknown value, it returns NotSupported.
470 IN EFI_SYSTEM_CONTEXT SystemContext
,
471 IN UINTN BreakpointNumber
475 BREAK_TYPE Type
= NotSupported
; // Default is NotSupported type
477 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
479 if (BreakpointNumber
== 1) {
480 Type
= (BREAK_TYPE
)Dr7
.Bits
.RW0
;
481 } else if (BreakpointNumber
== 2) {
482 Type
= (BREAK_TYPE
)Dr7
.Bits
.RW1
;
483 } else if (BreakpointNumber
== 3) {
484 Type
= (BREAK_TYPE
)Dr7
.Bits
.RW2
;
485 } else if (BreakpointNumber
== 4) {
486 Type
= (BREAK_TYPE
)Dr7
.Bits
.RW3
;
493 Parses Length and returns the length which DR7 LENn field accepts.
494 For example: If we receive 1-Byte length then we should return 0.
495 Zero gets written to DR7 LENn field.
497 @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
499 @retval Length Appropriate converted values which DR7 LENn field accepts.
510 } else if (Length
== 2) {
513 } else if (Length
== 4) {
517 // Undefined or 8-byte length
523 Finds the next free debug register. If all the registers are occupied then
524 EFI_OUT_OF_RESOURCES is returned.
526 @param SystemContext Register content at time of the exception
527 @param Register Register value (0 - 3 for the first free debug register)
529 @retval EFI_STATUS Appropriate status value.
533 FindNextFreeDebugRegister (
534 IN EFI_SYSTEM_CONTEXT SystemContext
,
540 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
542 if (Dr7
.Bits
.G0
== 0) {
544 } else if (Dr7
.Bits
.G1
== 0) {
546 } else if (Dr7
.Bits
.G2
== 0) {
548 } else if (Dr7
.Bits
.G3
== 0) {
551 return EFI_OUT_OF_RESOURCES
;
558 Enables the debug register. Writes Address value to appropriate DR0-3 register.
559 Sets LENn, Gn, RWn bits in DR7 register.
561 @param SystemContext Register content at time of the exception
562 @param Register Register value (0 - 3)
563 @param Address Breakpoint address value
564 @param Type Breakpoint type (Instruction, Data write,
565 Data read or write etc.)
567 @retval EFI_STATUS Appropriate status value.
571 EnableDebugRegister (
572 IN EFI_SYSTEM_CONTEXT SystemContext
,
581 // Convert length data
582 Length
= ConvertLengthData (Length
);
584 // For Instruction execution, length should be 0
585 // (Ref. Intel reference manual 18.2.4)
586 if ((Type
== 0) && (Length
!= 0)) {
587 return EFI_INVALID_PARAMETER
;
590 // Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
591 // software breakpoint. We should send empty packet in both these cases.
592 if ((Type
== (BREAK_TYPE
)DataRead
) ||
593 (Type
== (BREAK_TYPE
)SoftwareBreakpoint
))
595 return EFI_UNSUPPORTED
;
598 // Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
599 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
602 SystemContext
.SystemContextIa32
->Dr0
= Address
;
605 Dr7
.Bits
.LEN0
= Length
;
606 } else if (Register
== 1) {
607 SystemContext
.SystemContextIa32
->Dr1
= Address
;
610 Dr7
.Bits
.LEN1
= Length
;
611 } else if (Register
== 2) {
612 SystemContext
.SystemContextIa32
->Dr2
= Address
;
615 Dr7
.Bits
.LEN2
= Length
;
616 } else if (Register
== 3) {
617 SystemContext
.SystemContextIa32
->Dr3
= Address
;
620 Dr7
.Bits
.LEN3
= Length
;
622 return EFI_INVALID_PARAMETER
;
625 // Update Dr7 with appropriate Gn, RWn and LENn bits
626 SystemContext
.SystemContextIa32
->Dr7
= Dr7
.UintN
;
632 Returns register number 0 - 3 for the matching debug register.
633 This function compares incoming Address, Type, Length and
634 if there is a match then it returns the appropriate register number.
635 In case of mismatch, function returns EFI_NOT_FOUND message.
637 @param SystemContext Register content at time of the exception
638 @param Address Breakpoint address value
639 @param Length Breakpoint length value
640 @param Type Breakpoint type (Instruction, Data write, Data read
642 @param Register Register value to be returned
644 @retval EFI_STATUS Appropriate status value.
648 FindMatchingDebugRegister (
649 IN EFI_SYSTEM_CONTEXT SystemContext
,
658 // Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
659 // software breakpoint. We should send empty packet in both these cases.
660 if ((Type
== (BREAK_TYPE
)DataRead
) ||
661 (Type
== (BREAK_TYPE
)SoftwareBreakpoint
))
663 return EFI_UNSUPPORTED
;
666 // Convert length data
667 Length
= ConvertLengthData (Length
);
669 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
671 if ((Dr7
.Bits
.G0
== 1) &&
672 (Dr7
.Bits
.LEN0
== Length
) &&
673 (Dr7
.Bits
.RW0
== Type
) &&
674 (Address
== SystemContext
.SystemContextIa32
->Dr0
))
677 } else if ((Dr7
.Bits
.G1
== 1) &&
678 (Dr7
.Bits
.LEN1
== Length
) &&
679 (Dr7
.Bits
.RW1
== Type
) &&
680 (Address
== SystemContext
.SystemContextIa32
->Dr1
))
683 } else if ((Dr7
.Bits
.G2
== 1) &&
684 (Dr7
.Bits
.LEN2
== Length
) &&
685 (Dr7
.Bits
.RW2
== Type
) &&
686 (Address
== SystemContext
.SystemContextIa32
->Dr2
))
689 } else if ((Dr7
.Bits
.G3
== 1) &&
690 (Dr7
.Bits
.LEN3
== Length
) &&
691 (Dr7
.Bits
.RW3
== Type
) &&
692 (Address
== SystemContext
.SystemContextIa32
->Dr3
))
696 Print ((CHAR16
*)L
"No match found..\n");
697 return EFI_NOT_FOUND
;
704 Disables the particular debug register.
706 @param SystemContext Register content at time of the exception
707 @param Register Register to be disabled
709 @retval EFI_STATUS Appropriate status value.
713 DisableDebugRegister (
714 IN EFI_SYSTEM_CONTEXT SystemContext
,
721 // Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
722 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
725 SystemContext
.SystemContextIa32
->Dr0
= Address
;
729 } else if (Register
== 1) {
730 SystemContext
.SystemContextIa32
->Dr1
= Address
;
734 } else if (Register
== 2) {
735 SystemContext
.SystemContextIa32
->Dr2
= Address
;
739 } else if (Register
== 3) {
740 SystemContext
.SystemContextIa32
->Dr3
= Address
;
745 return EFI_INVALID_PARAMETER
;
748 // Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
749 SystemContext
.SystemContextIa32
->Dr7
= Dr7
.UintN
;
755 ‘Z1, [addr], [length]’
756 ‘Z2, [addr], [length]’
757 ‘Z3, [addr], [length]’
758 ‘Z4, [addr], [length]’
760 Insert hardware breakpoint/watchpoint at address addr of size length
762 @param SystemContext Register content at time of the exception
763 @param *PacketData Pointer to the Payload data for the packet
769 IN EFI_SYSTEM_CONTEXT SystemContext
,
778 BREAK_TYPE BreakType
= NotSupported
;
781 ErrorCode
= ParseBreakpointPacket (PacketData
, &Type
, &Address
, &Length
);
783 SendError ((UINT8
)ErrorCode
);
788 case 0: // Software breakpoint
789 BreakType
= SoftwareBreakpoint
;
792 case 1: // Hardware breakpoint
793 BreakType
= InstructionExecution
;
796 case 2: // Write watchpoint
797 BreakType
= DataWrite
;
800 case 3: // Read watchpoint
801 BreakType
= DataRead
;
804 case 4: // Access watchpoint
805 BreakType
= DataReadWrite
;
809 Print ((CHAR16
*)L
"Insert breakpoint default: %x\n", Type
);
810 SendError (GDB_EINVALIDBRKPOINTTYPE
);
814 // Find next free debug register
815 Status
= FindNextFreeDebugRegister (SystemContext
, &Register
);
816 if (EFI_ERROR (Status
)) {
817 Print ((CHAR16
*)L
"No space left on device\n");
818 SendError (GDB_ENOSPACE
);
822 // Write Address, length data at particular DR register
823 Status
= EnableDebugRegister (SystemContext
, Register
, Address
, Length
, (UINTN
)BreakType
);
824 if (EFI_ERROR (Status
)) {
825 if (Status
== EFI_UNSUPPORTED
) {
826 Print ((CHAR16
*)L
"Not supported\n");
831 Print ((CHAR16
*)L
"Invalid argument\n");
832 SendError (GDB_EINVALIDARG
);
840 ‘z1, [addr], [length]’
841 ‘z2, [addr], [length]’
842 ‘z3, [addr], [length]’
843 ‘z4, [addr], [length]’
845 Remove hardware breakpoint/watchpoint at address addr of size length
847 @param *PacketData Pointer to the Payload data for the packet
853 IN EFI_SYSTEM_CONTEXT SystemContext
,
861 BREAK_TYPE BreakType
= NotSupported
;
865 // Parse breakpoint packet data
866 ErrorCode
= ParseBreakpointPacket (PacketData
, &Type
, &Address
, &Length
);
868 SendError ((UINT8
)ErrorCode
);
873 case 0: // Software breakpoint
874 BreakType
= SoftwareBreakpoint
;
877 case 1: // Hardware breakpoint
878 BreakType
= InstructionExecution
;
881 case 2: // Write watchpoint
882 BreakType
= DataWrite
;
885 case 3: // Read watchpoint
886 BreakType
= DataRead
;
889 case 4: // Access watchpoint
890 BreakType
= DataReadWrite
;
894 SendError (GDB_EINVALIDBRKPOINTTYPE
);
898 // Find matching debug register
899 Status
= FindMatchingDebugRegister (SystemContext
, Address
, Length
, (UINTN
)BreakType
, &Register
);
900 if (EFI_ERROR (Status
)) {
901 if (Status
== EFI_UNSUPPORTED
) {
902 Print ((CHAR16
*)L
"Not supported.\n");
907 Print ((CHAR16
*)L
"No matching register found.\n");
908 SendError (GDB_ENOSPACE
);
913 Status
= DisableDebugRegister (SystemContext
, Register
);
914 if (EFI_ERROR (Status
)) {
915 Print ((CHAR16
*)L
"Invalid argument.\n");
916 SendError (GDB_EINVALIDARG
);
924 InitializeProcessor (
940 IN EFI_EXCEPTION_TYPE ExceptionType
,
941 IN OUT EFI_SYSTEM_CONTEXT SystemContext