2 UEFI driver that implements a GDB stub
4 Note: Any code in the path of the Serial IO output can not call DEBUG as will
5 will blow out the stack. Serial IO calls DEBUG, debug calls Serial IO, ...
8 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
10 SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include <GdbStubInternal.h>
15 #include <Protocol/DebugPort.h>
17 UINTN gMaxProcessorIndex
= 0;
20 // Buffers for basic gdb communication
22 CHAR8 gInBuffer
[MAX_BUF_SIZE
];
23 CHAR8 gOutBuffer
[MAX_BUF_SIZE
];
25 // Assume gdb does a "qXfer:libraries:read::offset,length" when it connects so we can default
26 // this value to FALSE. Since gdb can reconnect its self a global default is not good enough
27 BOOLEAN gSymbolTableUpdate
= FALSE
;
29 VOID
*gGdbSymbolEventHandlerRegistration
= NULL
;
32 // Globals for returning XML from qXfer:libraries:read packet
34 UINTN gPacketqXferLibraryOffset
= 0;
35 UINTN gEfiDebugImageTableEntry
= 0;
36 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
*gDebugImageTableHeader
= NULL
;
37 EFI_DEBUG_IMAGE_INFO
*gDebugTable
= NULL
;
38 CHAR8 gXferLibraryBuffer
[2000];
40 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexToStr
[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
44 GdbSymbolEventHandler (
52 The user Entry Point for Application. The user code starts with this function
53 as the real entry point for the image goes into a library that calls this
56 @param[in] ImageHandle The firmware allocated handle for the EFI image.
57 @param[in] SystemTable A pointer to the EFI System Table.
59 @retval EFI_SUCCESS The entry point is executed successfully.
60 @retval other Some error occurs when executing this entry point.
66 IN EFI_HANDLE ImageHandle
,
67 IN EFI_SYSTEM_TABLE
*SystemTable
71 EFI_DEBUG_SUPPORT_PROTOCOL
*DebugSupport
;
78 Status
= EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid
, (VOID
**)&gDebugImageTableHeader
);
79 if (EFI_ERROR (Status
)) {
80 gDebugImageTableHeader
= NULL
;
83 Status
= gBS
->LocateHandleBuffer (
85 &gEfiDebugSupportProtocolGuid
,
90 if (EFI_ERROR (Status
)) {
91 DEBUG ((DEBUG_ERROR
, "Debug Support Protocol not found\n"));
100 Status
= gBS
->HandleProtocol (
101 Handles
[HandleCount
],
102 &gEfiDebugSupportProtocolGuid
,
103 (VOID
**)&DebugSupport
105 if (!EFI_ERROR (Status
)) {
106 if (CheckIsa (DebugSupport
->Isa
)) {
107 // We found what we are looking for so break out of the loop
112 } while (HandleCount
> 0);
117 DEBUG ((DEBUG_ERROR
, "Debug Support Protocol does not support our ISA\n"));
119 return EFI_NOT_FOUND
;
122 Status
= DebugSupport
->GetMaximumProcessorIndex (DebugSupport
, &gMaxProcessorIndex
);
123 ASSERT_EFI_ERROR (Status
);
125 DEBUG ((DEBUG_INFO
, "Debug Support Protocol ISA %x\n", DebugSupport
->Isa
));
126 DEBUG ((DEBUG_INFO
, "Debug Support Protocol Processor Index %d\n", gMaxProcessorIndex
));
128 // Call processor-specific init routine
129 InitializeProcessor ();
131 for (Processor
= 0; Processor
<= gMaxProcessorIndex
; Processor
++) {
132 for (Index
= 0; Index
< MaxEfiException (); Index
++) {
133 Status
= DebugSupport
->RegisterExceptionCallback (DebugSupport
, Processor
, GdbExceptionHandler
, gExceptionType
[Index
].Exception
);
134 ASSERT_EFI_ERROR (Status
);
138 // Current edk2 DebugPort is not interrupt context safe so we can not use it
140 Status
= DebugSupport
->RegisterPeriodicCallback (DebugSupport
, Processor
, GdbPeriodicCallBack
);
141 ASSERT_EFI_ERROR (Status
);
145 // This even fires every time an image is added. This allows the stub to know when gdb needs
146 // to update the symbol table.
148 Status
= gBS
->CreateEvent (
151 GdbSymbolEventHandler
,
155 ASSERT_EFI_ERROR (Status
);
158 // Register for protocol notifications on this event
160 Status
= gBS
->RegisterProtocolNotify (
161 &gEfiLoadedImageProtocolGuid
,
163 &gGdbSymbolEventHandlerRegistration
165 ASSERT_EFI_ERROR (Status
);
167 if (PcdGetBool (PcdGdbSerial
)) {
168 GdbInitializeSerialConsole ();
175 Transfer length bytes of input buffer, starting at Address, to memory.
177 @param length the number of the bytes to be transferred/written
178 @param *address the start address of the transferring/writing the memory
179 @param *new_data the new data to be written to memory
182 TransferFromInBufToMem (
184 IN
unsigned char *Address
,
191 while (Length
-- > 0) {
192 c1
= (CHAR8
)HexCharToInt (*NewData
++);
193 c2
= (CHAR8
)HexCharToInt (*NewData
++);
195 if ((c1
< 0) || (c2
< 0)) {
196 Print ((CHAR16
*)L
"Bad message from write to memory..\n");
197 SendError (GDB_EBADMEMDATA
);
201 *Address
++ = (UINT8
)((c1
<< 4) + c2
);
208 Transfer Length bytes of memory starting at Address to an output buffer, OutBuffer. This function will finally send the buffer
211 @param Length the number of the bytes to be transferred/read
212 @param *address pointer to the start address of the transferring/reading the memory
215 TransferFromMemToOutBufAndSend (
217 IN
unsigned char *Address
220 // there are Length bytes and every byte is represented as 2 hex chars
221 CHAR8 OutBuffer
[MAX_BUF_SIZE
];
222 CHAR8
*OutBufPtr
; // pointer to the output buffer
225 if (ValidateAddress (Address
) == FALSE
) {
230 OutBufPtr
= OutBuffer
;
232 Char
= mHexToStr
[*Address
>> 4];
233 if ((Char
>= 'A') && (Char
<= 'F')) {
234 Char
= Char
- 'A' + 'a';
239 Char
= mHexToStr
[*Address
& 0x0f];
240 if ((Char
>= 'A') && (Char
<= 'F')) {
241 Char
= Char
- 'A' + 'a';
250 *OutBufPtr
= '\0'; // the end of the buffer
251 SendPacket (OutBuffer
);
255 Send a GDB Remote Serial Protocol Packet
257 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
258 the packet terminating character '#' and the two digit checksum.
260 If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up
261 in an infinite loop. This is so if you unplug the debugger code just keeps running
263 @param PacketData Payload data for the packet
266 @retval Number of bytes of packet data sent.
280 Timeout
= PcdGet32 (PcdGdbMaxPacketRetryCount
);
286 if (Timeout
-- == 0) {
287 // Only try a finite number of times so we don't get stuck in the loop
294 for (CheckSum
= 0, Count
= 0; *Ptr
!= '\0'; Ptr
++, Count
++) {
296 CheckSum
= CheckSum
+ *Ptr
;
299 // Packet terminating character and checksum
301 GdbPutChar (mHexToStr
[CheckSum
>> 4]);
302 GdbPutChar (mHexToStr
[CheckSum
& 0x0F]);
304 TestChar
= GdbGetChar ();
305 } while (TestChar
!= '+');
311 Receive a GDB Remote Serial Protocol Packet
313 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
314 the packet terminating character '#' and the two digit checksum.
316 If host re-starts sending a packet without ending the previous packet, only the last valid packet is processed.
317 (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)
319 If an ack '+' is not sent resend the packet
321 @param PacketData Payload data for the packet
323 @retval Number of bytes of packet data received.
328 OUT CHAR8
*PacketData
,
329 IN UINTN PacketDataSize
338 ZeroMem (PacketData
, PacketDataSize
);
341 // wait for the start of a packet
342 TestChar
= GdbGetChar ();
343 while (TestChar
!= '$') {
344 TestChar
= GdbGetChar ();
348 for (Index
= 0, CheckSum
= 0; Index
< (PacketDataSize
- 1); Index
++) {
349 Char
= GdbGetChar ();
358 PacketData
[Index
] = Char
;
359 CheckSum
= CheckSum
+ Char
;
362 PacketData
[Index
] = '\0';
364 if (Index
== PacketDataSize
) {
368 SumString
[0] = GdbGetChar ();
369 SumString
[1] = GdbGetChar ();
372 if (AsciiStrHexToUintn (SumString
) == CheckSum
) {
376 // Null terminate the callers string
377 PacketData
[Index
] = '\0';
389 Empties the given buffer
390 @param Buf pointer to the first element in buffer to be emptied
401 Converts an 8-bit Hex Char into a INTN.
403 @param Char the hex character to be converted into UINTN
404 @retval a INTN, from 0 to 15, that corresponds to Char
405 -1 if Char is not a hex character
412 if ((Char
>= 'A') && (Char
<= 'F')) {
413 return Char
- 'A' + 10;
414 } else if ((Char
>= 'a') && (Char
<= 'f')) {
415 return Char
- 'a' + 10;
416 } else if ((Char
>= '0') && (Char
<= '9')) {
419 // if not a hex value, return a negative value
424 // 'E' + the biggest error number is 255, so its 2 hex digits + buffer end
425 CHAR8
*gError
= "E__";
428 Send an error with the given error number after converting to hex.
429 The error number is put into the buffer in hex. '255' is the biggest errno we can send.
430 ex: 162 will be sent as A2.
432 @param errno the error number that will be sent
441 // Replace _, or old data, with current errno
443 gError
[1] = mHexToStr
[ErrorNum
>> 4];
444 gError
[2] = mHexToStr
[ErrorNum
& 0x0f];
446 SendPacket (gError
); // send buffer
450 Send 'OK' when the function is done executing successfully.
458 SendPacket ("OK"); // send buffer
462 Send empty packet to specify that particular command/functionality is not supported.
474 Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints
476 @param SystemContext Register content at time of the exception
477 @param GdbExceptionType GDB exception type
481 IN EFI_SYSTEM_CONTEXT SystemContext
,
482 IN UINT8 GdbExceptionType
485 CHAR8 TSignalBuffer
[128];
487 UINTN BreakpointDetected
;
488 BREAK_TYPE BreakType
;
490 CHAR8
*WatchStrPtr
= NULL
;
493 TSignalPtr
= &TSignalBuffer
[0];
495 // Construct TSignal packet
499 // replace _, or previous value, with Exception type
501 *TSignalPtr
++ = mHexToStr
[GdbExceptionType
>> 4];
502 *TSignalPtr
++ = mHexToStr
[GdbExceptionType
& 0x0f];
504 if (GdbExceptionType
== GDB_SIGTRAP
) {
505 if (gSymbolTableUpdate
) {
507 // We can only send back on reason code. So if the flag is set it means the breakpoint is from our event handler
509 WatchStrPtr
= "library:;";
510 while (*WatchStrPtr
!= '\0') {
511 *TSignalPtr
++ = *WatchStrPtr
++;
514 gSymbolTableUpdate
= FALSE
;
517 // possible n:r pairs
520 // Retrieve the breakpoint number
521 BreakpointDetected
= GetBreakpointDetected (SystemContext
);
523 // Figure out if the exception is happend due to watch, rwatch or awatch.
524 BreakType
= GetBreakpointType (SystemContext
, BreakpointDetected
);
526 // INFO: rwatch is not supported due to the way IA32 debug registers work
527 if ((BreakType
== DataWrite
) || (BreakType
== DataRead
) || (BreakType
== DataReadWrite
)) {
528 // Construct n:r pair
529 DataAddress
= GetBreakpointDataAddress (SystemContext
, BreakpointDetected
);
531 // Assign appropriate buffer to print particular watchpoint type
532 if (BreakType
== DataWrite
) {
533 WatchStrPtr
= "watch";
534 } else if (BreakType
== DataRead
) {
535 WatchStrPtr
= "rwatch";
536 } else if (BreakType
== DataReadWrite
) {
537 WatchStrPtr
= "awatch";
540 while (*WatchStrPtr
!= '\0') {
541 *TSignalPtr
++ = *WatchStrPtr
++;
546 // Set up series of bytes in big-endian byte order. "awatch" won't work with little-endian byte order.
548 while (RegSize
> 0) {
550 *TSignalPtr
++ = mHexToStr
[(UINT8
)(DataAddress
>> RegSize
) & 0xf];
553 // Always end n:r pair with ';'
561 SendPacket (TSignalBuffer
);
565 Translates the EFI mapping to GDB mapping
567 @param EFIExceptionType EFI Exception that is being processed
568 @retval UINTN that corresponds to EFIExceptionType's GDB exception type number
571 ConvertEFItoGDBtype (
572 IN EFI_EXCEPTION_TYPE EFIExceptionType
577 for (Index
= 0; Index
< MaxEfiException (); Index
++) {
578 if (gExceptionType
[Index
].Exception
== EFIExceptionType
) {
579 return gExceptionType
[Index
].SignalNo
;
583 return GDB_SIGTRAP
; // this is a GDB trap
587 Find the Length of the area to read and the start address. Finally, pass them to
588 another function, TransferFromMemToOutBufAndSend, that will read from that memory space and
599 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
]; // the buffer that will hold the address in hex chars
600 CHAR8
*AddrBufPtr
; // pointer to the address buffer
601 CHAR8
*InBufPtr
; /// pointer to the input buffer
603 AddrBufPtr
= AddressBuffer
;
604 InBufPtr
= &PacketData
[1];
605 while (*InBufPtr
!= ',') {
606 *AddrBufPtr
++ = *InBufPtr
++;
611 InBufPtr
++; // this skips ',' in the buffer
614 if (AsciiStrLen (AddressBuffer
) >= MAX_ADDR_SIZE
) {
615 Print ((CHAR16
*)L
"Address is too long\n");
616 SendError (GDB_EBADMEMADDRBUFSIZE
);
621 if (AsciiStrLen (PacketData
) - AsciiStrLen (AddressBuffer
) - 2 >= MAX_LENGTH_SIZE
) {
622 Print ((CHAR16
*)L
"Length is too long\n");
623 SendError (GDB_EBADMEMLENGTH
);
627 Address
= AsciiStrHexToUintn (AddressBuffer
);
628 Length
= AsciiStrHexToUintn (InBufPtr
);
630 TransferFromMemToOutBufAndSend (Length
, (unsigned char *)Address
);
633 /** "M addr,length :XX..."
634 Find the Length of the area in bytes to write and the start address. Finally, pass them to
635 another function, TransferFromInBufToMem, that will write to that memory space the info in
647 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
]; // the buffer that will hold the Address in hex chars
648 CHAR8 LengthBuffer
[MAX_LENGTH_SIZE
]; // the buffer that will hold the Length in hex chars
649 CHAR8
*AddrBufPtr
; // pointer to the Address buffer
650 CHAR8
*LengthBufPtr
; // pointer to the Length buffer
651 CHAR8
*InBufPtr
; /// pointer to the input buffer
653 AddrBufPtr
= AddressBuffer
;
654 LengthBufPtr
= LengthBuffer
;
655 InBufPtr
= &PacketData
[1];
657 while (*InBufPtr
!= ',') {
658 *AddrBufPtr
++ = *InBufPtr
++;
663 InBufPtr
++; // this skips ',' in the buffer
665 while (*InBufPtr
!= ':') {
666 *LengthBufPtr
++ = *InBufPtr
++;
669 *LengthBufPtr
= '\0';
671 InBufPtr
++; // this skips ':' in the buffer
673 Address
= AsciiStrHexToUintn (AddressBuffer
);
674 Length
= AsciiStrHexToUintn (LengthBuffer
);
678 // Check if Address is not too long.
679 if (AsciiStrLen (AddressBuffer
) >= MAX_ADDR_SIZE
) {
680 Print ((CHAR16
*)L
"Address too long..\n");
681 SendError (GDB_EBADMEMADDRBUFSIZE
);
685 // Check if message length is not too long
686 if (AsciiStrLen (LengthBuffer
) >= MAX_LENGTH_SIZE
) {
687 Print ((CHAR16
*)L
"Length too long..\n");
688 SendError (GDB_EBADMEMLENGBUFSIZE
);
692 // Check if Message is not too long/short.
693 // 3 = 'M' + ',' + ':'
694 MessageLength
= (AsciiStrLen (PacketData
) - AsciiStrLen (AddressBuffer
) - AsciiStrLen (LengthBuffer
) - 3);
695 if (MessageLength
!= (2*Length
)) {
696 // Message too long/short. New data is not the right size.
697 SendError (GDB_EBADMEMDATASIZE
);
701 TransferFromInBufToMem (Length
, (unsigned char *)Address
, InBufPtr
);
705 Parses breakpoint packet data and captures Breakpoint type, Address and length.
706 In case of an error, function returns particular error code. Returning 0 meaning
709 @param PacketData Pointer to the payload data for the packet.
710 @param Type Breakpoint type
711 @param Address Breakpoint address
712 @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
715 @retval {other} Particular error code
719 ParseBreakpointPacket (
720 IN CHAR8
*PacketData
,
726 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
];
727 CHAR8
*AddressBufferPtr
;
728 CHAR8
*PacketDataPtr
;
730 PacketDataPtr
= &PacketData
[1];
731 AddressBufferPtr
= AddressBuffer
;
733 *Type
= AsciiStrHexToUintn (PacketDataPtr
);
735 // Breakpoint/watchpoint type should be between 0 to 4
737 Print ((CHAR16
*)L
"Type is invalid\n");
738 return 22; // EINVAL: Invalid argument.
741 // Skip ',' in the buffer.
742 while (*PacketDataPtr
++ != ',') {
745 // Parse Address information
746 while (*PacketDataPtr
!= ',') {
747 *AddressBufferPtr
++ = *PacketDataPtr
++;
750 *AddressBufferPtr
= '\0';
752 // Check if Address is not too long.
753 if (AsciiStrLen (AddressBuffer
) >= MAX_ADDR_SIZE
) {
754 Print ((CHAR16
*)L
"Address too long..\n");
755 return 40; // EMSGSIZE: Message size too long.
758 *Address
= AsciiStrHexToUintn (AddressBuffer
);
760 PacketDataPtr
++; // This skips , in the buffer
762 // Parse Length information
763 *Length
= AsciiStrHexToUintn (PacketDataPtr
);
765 // Length should be 1, 2 or 4 bytes
767 Print ((CHAR16
*)L
"Length is invalid\n");
768 return 22; // EINVAL: Invalid argument
771 return 0; // 0 = No error
775 gXferObjectReadResponse (
780 CHAR8
*OutBufPtr
; // pointer to the output buffer
784 // Response starts with 'm' or 'l' if it is the end
785 OutBufPtr
= gOutBuffer
;
789 // Binary data encoding
790 OutBufPtr
= gOutBuffer
;
791 while (*Str
!= '\0') {
793 if ((Char
== 0x7d) || (Char
== 0x23) || (Char
== 0x24) || (Char
== 0x2a)) {
804 *OutBufPtr
= '\0'; // the end of the buffer
805 SendPacket (gOutBuffer
);
811 Note: This should be a library function. In the Apple case you have to add
812 the size of the PE/COFF header into the starting address to make things work
813 right as there is no way to pad the Mach-O for the size of the PE/COFF header.
816 Returns a pointer to the PDB file name for a PE/COFF image that has been
817 loaded into system memory with the PE/COFF Loader Library functions.
819 Returns the PDB file name for the PE/COFF image specified by Pe32Data. If
820 the PE/COFF image specified by Pe32Data is not a valid, then NULL is
821 returned. If the PE/COFF image specified by Pe32Data does not contain a
822 debug directory entry, then NULL is returned. If the debug directory entry
823 in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
824 then NULL is returned.
825 If Pe32Data is NULL, then ASSERT().
827 @param Pe32Data Pointer to the PE/COFF image that is loaded in system
829 @param DebugBase Address that the debugger would use as the base of the image
831 @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
832 if it cannot be retrieved. DebugBase is only valid if PDB file name is
838 PeCoffLoaderGetDebuggerInfo (
843 EFI_IMAGE_DOS_HEADER
*DosHdr
;
844 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
845 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
846 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
848 VOID
*CodeViewEntryPointer
;
850 UINT32 NumberOfRvaAndSizes
;
854 ASSERT (Pe32Data
!= NULL
);
857 DirectoryEntry
= NULL
;
859 NumberOfRvaAndSizes
= 0;
862 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
863 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
865 // DOS image header is present, so read the PE header after the DOS image header.
867 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)Pe32Data
+ (UINTN
)((DosHdr
->e_lfanew
) & 0x0ffff));
870 // DOS image header is not present, so PE header is at the image base.
872 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
875 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
876 if (Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
!= 0) {
877 DirectoryEntry
= &Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
];
878 TEImageAdjust
= sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
;
879 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)((UINTN
)Hdr
.Te
+
880 Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
+
884 SizeOfHeaders
= sizeof (EFI_TE_IMAGE_HEADER
) + (UINTN
)Hdr
.Te
->BaseOfCode
- (UINTN
)Hdr
.Te
->StrippedSize
;
886 // __APPLE__ check this math...
887 *DebugBase
= ((CHAR8
*)Pe32Data
) - TEImageAdjust
;
888 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
889 *DebugBase
= Pe32Data
;
892 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
893 // It is due to backward-compatibility, for some system might
894 // generate PE32+ image with PE32 Magic.
896 switch (Hdr
.Pe32
->FileHeader
.Machine
) {
897 case EFI_IMAGE_MACHINE_IA32
:
899 // Assume PE32 image with IA32 Machine field.
901 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
903 case EFI_IMAGE_MACHINE_X64
:
904 case EFI_IMAGE_MACHINE_IA64
:
906 // Assume PE32+ image with X64 or IPF Machine field
908 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
912 // For unknown Machine field, use Magic in optional Header
914 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
917 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
919 // Use PE32 offset get Debug Directory Entry
921 SizeOfHeaders
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
;
922 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
923 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
924 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)((UINTN
)Pe32Data
+ DirectoryEntry
->VirtualAddress
);
925 } else if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
927 // Use PE32+ offset get Debug Directory Entry
929 SizeOfHeaders
= Hdr
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
930 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
931 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
932 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)((UINTN
)Pe32Data
+ DirectoryEntry
->VirtualAddress
);
935 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
936 DirectoryEntry
= NULL
;
943 if ((DebugEntry
== NULL
) || (DirectoryEntry
== NULL
)) {
947 for (DirCount
= 0; DirCount
< DirectoryEntry
->Size
; DirCount
+= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
), DebugEntry
++) {
948 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
949 if (DebugEntry
->SizeOfData
> 0) {
950 CodeViewEntryPointer
= (VOID
*)((UINTN
)DebugEntry
->RVA
+ ((UINTN
)Pe32Data
) + (UINTN
)TEImageAdjust
);
951 switch (*(UINT32
*)CodeViewEntryPointer
) {
952 case CODEVIEW_SIGNATURE_NB10
:
953 return (VOID
*)((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
));
954 case CODEVIEW_SIGNATURE_RSDS
:
955 return (VOID
*)((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
));
956 case CODEVIEW_SIGNATURE_MTOC
:
957 *DebugBase
= (VOID
*)(UINTN
)((UINTN
)DebugBase
- SizeOfHeaders
);
958 return (VOID
*)((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY
));
971 Process "qXfer:object:read:annex:offset,length" request.
973 Returns an XML document that contains loaded libraries. In our case it is
974 information in the EFI Debug Image Table converted into an XML document.
976 GDB will call with an arbitrary length (it can't know the real length and
977 will reply with chunks of XML that are easy for us to deal with. Gdb will
978 keep calling until we say we are done. XML doc looks like:
981 <library name="/a/a/c/d.dSYM"><segment address="0x10000000"/></library>
982 <library name="/a/m/e/e.pdb"><segment address="0x20000000"/></library>
983 <library name="/a/l/f/f.dll"><segment address="0x30000000"/></library>
986 Since we can not allocate memory in interrupt context this module has
987 assumptions about how it will get called:
988 1) Length will generally be max remote packet size (big enough)
989 2) First Offset of an XML document read needs to be 0
990 3) This code will return back small chunks of the XML document on every read.
991 Each subsequent call will ask for the next available part of the document.
993 Note: The only variable size element in the XML is:
994 " <library name=\"%s\"><segment address=\"%p\"/></library>\n" and it is
995 based on the file path and name of the symbol file. If the symbol file name
996 is bigger than the max gdb remote packet size we could update this code
997 to respond back in chunks.
999 @param Offset offset into special data area
1000 @param Length number of bytes to read starting at Offset
1013 if (Offset
!= gPacketqXferLibraryOffset
) {
1014 SendError (GDB_EINVALIDARG
);
1015 Print (L
"\nqXferLibrary (%d, %d) != %d\n", Offset
, Length
, gPacketqXferLibraryOffset
);
1017 // Force a retry from the beginning
1018 gPacketqXferLibraryOffset
= 0;
1024 gPacketqXferLibraryOffset
+= gXferObjectReadResponse ('m', "<library-list>\n");
1026 // The owner of the table may have had to ralloc it so grab a fresh copy every time
1027 // we assume qXferLibrary will get called over and over again until the entire XML table is
1028 // returned in a tight loop. Since we are in the debugger the table should not get updated
1029 gDebugTable
= gDebugImageTableHeader
->EfiDebugImageInfoTable
;
1030 gEfiDebugImageTableEntry
= 0;
1034 if (gDebugTable
!= NULL
) {
1035 for ( ; gEfiDebugImageTableEntry
< gDebugImageTableHeader
->TableSize
; gEfiDebugImageTableEntry
++, gDebugTable
++) {
1036 if (gDebugTable
->NormalImage
!= NULL
) {
1037 if ((gDebugTable
->NormalImage
->ImageInfoType
== EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
) &&
1038 (gDebugTable
->NormalImage
->LoadedImageProtocolInstance
!= NULL
))
1040 Pdb
= PeCoffLoaderGetDebuggerInfo (
1041 gDebugTable
->NormalImage
->LoadedImageProtocolInstance
->ImageBase
,
1045 Size
= AsciiSPrint (
1047 sizeof (gXferLibraryBuffer
),
1048 " <library name=\"%a\"><segment address=\"0x%p\"/></library>\n",
1052 if ((Size
!= 0) && (Size
!= (sizeof (gXferLibraryBuffer
) - 1))) {
1053 gPacketqXferLibraryOffset
+= gXferObjectReadResponse ('m', gXferLibraryBuffer
);
1055 // Update loop variables so we are in the right place when we get back
1056 gEfiDebugImageTableEntry
++;
1060 // We could handle <library> entires larger than sizeof (gXferLibraryBuffer) here if
1061 // needed by breaking up into N packets
1062 // "<library name=\"%s
1063 // the rest of the string (as many packets as required
1064 // \"><segment address=\"%d\"/></library> (fixed size)
1066 // But right now we just skip any entry that is too big
1074 gXferObjectReadResponse ('l', "</library-list>\n");
1075 gPacketqXferLibraryOffset
= 0;
1080 Exception Handler for GDB. It will be called for all exceptions
1081 registered via the gExceptionType[] array.
1083 @param ExceptionType Exception that is being processed
1084 @param SystemContext Register content at time of the exception
1088 GdbExceptionHandler (
1089 IN EFI_EXCEPTION_TYPE ExceptionType
,
1090 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1093 UINT8 GdbExceptionType
;
1096 if (ValidateException (ExceptionType
, SystemContext
) == FALSE
) {
1100 RemoveSingleStep (SystemContext
);
1102 GdbExceptionType
= ConvertEFItoGDBtype (ExceptionType
);
1103 GdbSendTSignal (SystemContext
, GdbExceptionType
);
1106 ReceivePacket (gInBuffer
, MAX_BUF_SIZE
);
1108 switch (gInBuffer
[0]) {
1110 GdbSendTSignal (SystemContext
, GdbExceptionType
);
1114 ContinueAtAddress (SystemContext
, gInBuffer
);
1118 ReadGeneralRegisters (SystemContext
);
1122 WriteGeneralRegisters (SystemContext
, gInBuffer
);
1126 // Return "OK" packet since we don't have more than one thread.
1131 ReadFromMemory (gInBuffer
);
1135 WriteToMemory (gInBuffer
);
1139 WriteNthRegister (SystemContext
, gInBuffer
);
1143 // Still debugging this code. Not used in Darwin
1146 // General Query Packets
1147 if (AsciiStrnCmp (gInBuffer
, "qSupported", 10) == 0) {
1148 // return what we currently support, we don't parse what gdb supports
1149 AsciiSPrint (gOutBuffer
, MAX_BUF_SIZE
, "qXfer:libraries:read+;PacketSize=%d", MAX_BUF_SIZE
);
1150 SendPacket (gOutBuffer
);
1151 } else if (AsciiStrnCmp (gInBuffer
, "qXfer:libraries:read::", 22) == 0) {
1152 // ‘qXfer:libraries:read::offset,length
1153 // gInBuffer[22] is offset string, ++Ptr is length string’
1154 for (Ptr
= &gInBuffer
[22]; *Ptr
!= ','; Ptr
++) {
1157 // Not sure if multi-radix support is required. Currently only support decimal
1158 QxferLibrary (AsciiStrHexToUintn (&gInBuffer
[22]), AsciiStrHexToUintn (++Ptr
));
1161 if (AsciiStrnCmp (gInBuffer
, "qOffsets", 10) == 0) {
1162 AsciiSPrint (gOutBuffer
, MAX_BUF_SIZE
, "Text=1000;Data=f000;Bss=f000");
1163 SendPacket (gOutBuffer
);
1165 // Send empty packet
1166 SendNotSupported ();
1172 SingleStep (SystemContext
, gInBuffer
);
1176 RemoveBreakPoint (SystemContext
, gInBuffer
);
1180 InsertBreakPoint (SystemContext
, gInBuffer
);
1184 // Send empty packet
1185 SendNotSupported ();
1192 Periodic callback for GDB. This function is used to catch a ctrl-c or other
1193 break in type command from GDB.
1195 @param SystemContext Register content at time of the call
1199 GdbPeriodicCallBack (
1200 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1204 // gCtrlCBreakFlag may have been set from a previous F response package
1205 // and we set the global as we need to process it at a point where we
1206 // can update the system context. If we are in the middle of processing
1207 // a F Packet it is not safe to read the GDB serial stream so we need
1208 // to skip it on this check
1210 if (!gCtrlCBreakFlag
&& !gProcessingFPacket
) {
1212 // Ctrl-C was not pending so grab any pending characters and see if they
1213 // are a Ctrl-c (0x03). If so set the Ctrl-C global.
1216 if (!GdbIsCharAvailable ()) {
1218 // No characters are pending so exit the loop
1223 if (GdbGetChar () == 0x03) {
1224 gCtrlCBreakFlag
= TRUE
;
1226 // We have a ctrl-c so exit the loop
1233 if (gCtrlCBreakFlag
) {
1235 // Update the context to force a single step trap when we exit the GDB
1236 // stub. This will transfer control to GdbExceptionHandler () and let
1237 // us break into the program. We don't want to break into the GDB stub.
1239 AddSingleStep (SystemContext
);
1240 gCtrlCBreakFlag
= FALSE
;