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 Serail 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>
18 UINTN gMaxProcessorIndex
= 0;
21 // Buffers for basic gdb communication
23 CHAR8 gInBuffer
[MAX_BUF_SIZE
];
24 CHAR8 gOutBuffer
[MAX_BUF_SIZE
];
26 // Assume gdb does a "qXfer:libraries:read::offset,length" when it connects so we can default
27 // this value to FALSE. Since gdb can reconnect its self a global default is not good enough
28 BOOLEAN gSymbolTableUpdate
= FALSE
;
30 VOID
*gGdbSymbolEventHandlerRegistration
= NULL
;
33 // Globals for returning XML from qXfer:libraries:read packet
35 UINTN gPacketqXferLibraryOffset
= 0;
36 UINTN gEfiDebugImageTableEntry
= 0;
37 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
*gDebugImageTableHeader
= NULL
;
38 EFI_DEBUG_IMAGE_INFO
*gDebugTable
= NULL
;
39 CHAR8 gXferLibraryBuffer
[2000];
41 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexToStr
[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
46 GdbSymbolEventHandler (
55 The user Entry Point for Application. The user code starts with this function
56 as the real entry point for the image goes into a library that calls this
59 @param[in] ImageHandle The firmware allocated handle for the EFI image.
60 @param[in] SystemTable A pointer to the EFI System Table.
62 @retval EFI_SUCCESS The entry point is executed successfully.
63 @retval other Some error occurs when executing this entry point.
69 IN EFI_HANDLE ImageHandle
,
70 IN EFI_SYSTEM_TABLE
*SystemTable
74 EFI_DEBUG_SUPPORT_PROTOCOL
*DebugSupport
;
81 Status
= EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid
, (VOID
**)&gDebugImageTableHeader
);
82 if (EFI_ERROR (Status
)) {
83 gDebugImageTableHeader
= NULL
;
86 Status
= gBS
->LocateHandleBuffer (
88 &gEfiDebugSupportProtocolGuid
,
93 if (EFI_ERROR (Status
)) {
94 DEBUG ((EFI_D_ERROR
, "Debug Support Protocol not found\n"));
100 IsaSupported
= FALSE
;
103 Status
= gBS
->HandleProtocol (
104 Handles
[HandleCount
],
105 &gEfiDebugSupportProtocolGuid
,
106 (VOID
**) &DebugSupport
108 if (!EFI_ERROR (Status
)) {
109 if (CheckIsa (DebugSupport
->Isa
)) {
110 // We found what we are looking for so break out of the loop
115 } while (HandleCount
> 0);
119 DEBUG ((EFI_D_ERROR
, "Debug Support Protocol does not support our ISA\n"));
121 return EFI_NOT_FOUND
;
124 Status
= DebugSupport
->GetMaximumProcessorIndex (DebugSupport
, &gMaxProcessorIndex
);
125 ASSERT_EFI_ERROR (Status
);
127 DEBUG ((EFI_D_INFO
, "Debug Support Protocol ISA %x\n", DebugSupport
->Isa
));
128 DEBUG ((EFI_D_INFO
, "Debug Support Protocol Processor Index %d\n", gMaxProcessorIndex
));
130 // Call processor-specific init routine
131 InitializeProcessor ();
133 for (Processor
= 0; Processor
<= gMaxProcessorIndex
; Processor
++) {
134 for (Index
= 0; Index
< MaxEfiException (); Index
++) {
135 Status
= DebugSupport
->RegisterExceptionCallback (DebugSupport
, Processor
, GdbExceptionHandler
, gExceptionType
[Index
].Exception
);
136 ASSERT_EFI_ERROR (Status
);
139 // Current edk2 DebugPort is not interrupt context safe so we can not use it
141 Status
= DebugSupport
->RegisterPeriodicCallback (DebugSupport
, Processor
, GdbPeriodicCallBack
);
142 ASSERT_EFI_ERROR (Status
);
146 // This even fires every time an image is added. This allows the stub to know when gdb needs
147 // to update the symbol table.
149 Status
= gBS
->CreateEvent (
152 GdbSymbolEventHandler
,
156 ASSERT_EFI_ERROR (Status
);
159 // Register for protocol notifications on this event
161 Status
= gBS
->RegisterProtocolNotify (
162 &gEfiLoadedImageProtocolGuid
,
164 &gGdbSymbolEventHandlerRegistration
166 ASSERT_EFI_ERROR (Status
);
169 if (PcdGetBool (PcdGdbSerial
)) {
170 GdbInitializeSerialConsole ();
177 Transfer length bytes of input buffer, starting at Address, to memory.
179 @param length the number of the bytes to be transferred/written
180 @param *address the start address of the transferring/writing the memory
181 @param *new_data the new data to be written to memory
185 TransferFromInBufToMem (
187 IN
unsigned char *Address
,
194 while (Length
-- > 0) {
195 c1
= (CHAR8
)HexCharToInt (*NewData
++);
196 c2
= (CHAR8
)HexCharToInt (*NewData
++);
198 if ((c1
< 0) || (c2
< 0)) {
199 Print ((CHAR16
*)L
"Bad message from write to memory..\n");
200 SendError (GDB_EBADMEMDATA
);
203 *Address
++ = (UINT8
)((c1
<< 4) + c2
);
211 Transfer Length bytes of memory starting at Address to an output buffer, OutBuffer. This function will finally send the buffer
214 @param Length the number of the bytes to be transferred/read
215 @param *address pointer to the start address of the transferring/reading the memory
219 TransferFromMemToOutBufAndSend (
221 IN
unsigned char *Address
224 // there are Length bytes and every byte is represented as 2 hex chars
225 CHAR8 OutBuffer
[MAX_BUF_SIZE
];
226 CHAR8
*OutBufPtr
; // pointer to the output buffer
229 if (ValidateAddress(Address
) == FALSE
) {
234 OutBufPtr
= OutBuffer
;
237 Char
= mHexToStr
[*Address
>> 4];
238 if ((Char
>= 'A') && (Char
<= 'F')) {
239 Char
= Char
- 'A' + 'a';
243 Char
= mHexToStr
[*Address
& 0x0f];
244 if ((Char
>= 'A') && (Char
<= 'F')) {
245 Char
= Char
- 'A' + 'a';
253 *OutBufPtr
= '\0' ; // the end of the buffer
254 SendPacket (OutBuffer
);
260 Send a GDB Remote Serial Protocol Packet
262 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
263 the packet teminating character '#' and the two digit checksum.
265 If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up
266 in an infinit loop. This is so if you unplug the debugger code just keeps running
268 @param PacketData Payload data for the packet
271 @retval Number of bytes of packet data sent.
285 Timeout
= PcdGet32 (PcdGdbMaxPacketRetryCount
);
292 if (Timeout
-- == 0) {
293 // Only try a finite number of times so we don't get stuck in the loop
300 for (CheckSum
= 0, Count
=0 ; *Ptr
!= '\0'; Ptr
++, Count
++) {
302 CheckSum
= CheckSum
+ *Ptr
;
305 // Packet terminating character and checksum
307 GdbPutChar (mHexToStr
[CheckSum
>> 4]);
308 GdbPutChar (mHexToStr
[CheckSum
& 0x0F]);
310 TestChar
= GdbGetChar ();
311 } while (TestChar
!= '+');
317 Receive a GDB Remote Serial Protocol Packet
319 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
320 the packet teminating character '#' and the two digit checksum.
322 If host re-starts sending a packet without ending the previous packet, only the last valid packet is processed.
323 (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)
325 If an ack '+' is not sent resend the packet
327 @param PacketData Payload data for the packet
329 @retval Number of bytes of packet data received.
334 OUT CHAR8
*PacketData
,
335 IN UINTN PacketDataSize
344 ZeroMem (PacketData
, PacketDataSize
);
347 // wait for the start of a packet
348 TestChar
= GdbGetChar ();
349 while (TestChar
!= '$') {
350 TestChar
= GdbGetChar ();
354 for (Index
= 0, CheckSum
= 0; Index
< (PacketDataSize
- 1); Index
++) {
355 Char
= GdbGetChar ();
363 PacketData
[Index
] = Char
;
364 CheckSum
= CheckSum
+ Char
;
366 PacketData
[Index
] = '\0';
368 if (Index
== PacketDataSize
) {
372 SumString
[0] = GdbGetChar ();
373 SumString
[1] = GdbGetChar ();
376 if (AsciiStrHexToUintn (SumString
) == CheckSum
) {
380 // Null terminate the callers string
381 PacketData
[Index
] = '\0';
394 Empties the given buffer
395 @param Buf pointer to the first element in buffer to be emptied
407 Converts an 8-bit Hex Char into a INTN.
409 @param Char the hex character to be converted into UINTN
410 @retval a INTN, from 0 to 15, that corressponds to Char
411 -1 if Char is not a hex character
418 if ((Char
>= 'A') && (Char
<= 'F')) {
419 return Char
- 'A' + 10;
420 } else if ((Char
>= 'a') && (Char
<= 'f')) {
421 return Char
- 'a' + 10;
422 } else if ((Char
>= '0') && (Char
<= '9')) {
424 } else { // if not a hex value, return a negative value
429 // 'E' + the biggest error number is 255, so its 2 hex digits + buffer end
430 CHAR8
*gError
= "E__";
433 Send an error with the given error number after converting to hex.
434 The error number is put into the buffer in hex. '255' is the biggest errno we can send.
435 ex: 162 will be sent as A2.
437 @param errno the error number that will be sent
446 // Replace _, or old data, with current errno
448 gError
[1] = mHexToStr
[ErrorNum
>> 4];
449 gError
[2] = mHexToStr
[ErrorNum
& 0x0f];
451 SendPacket (gError
); // send buffer
457 Send 'OK' when the function is done executing successfully.
465 SendPacket ("OK"); // send buffer
470 Send empty packet to specify that particular command/functionality is not supported.
483 Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints
485 @param SystemContext Register content at time of the exception
486 @param GdbExceptionType GDB exception type
490 IN EFI_SYSTEM_CONTEXT SystemContext
,
491 IN UINT8 GdbExceptionType
494 CHAR8 TSignalBuffer
[128];
496 UINTN BreakpointDetected
;
497 BREAK_TYPE BreakType
;
499 CHAR8
*WatchStrPtr
= NULL
;
502 TSignalPtr
= &TSignalBuffer
[0];
504 //Construct TSignal packet
508 // replace _, or previous value, with Exception type
510 *TSignalPtr
++ = mHexToStr
[GdbExceptionType
>> 4];
511 *TSignalPtr
++ = mHexToStr
[GdbExceptionType
& 0x0f];
513 if (GdbExceptionType
== GDB_SIGTRAP
) {
514 if (gSymbolTableUpdate
) {
516 // We can only send back on reason code. So if the flag is set it means the breakpoint is from our event handler
518 WatchStrPtr
= "library:;";
519 while (*WatchStrPtr
!= '\0') {
520 *TSignalPtr
++ = *WatchStrPtr
++;
522 gSymbolTableUpdate
= FALSE
;
527 // possible n:r pairs
530 //Retrieve the breakpoint number
531 BreakpointDetected
= GetBreakpointDetected (SystemContext
);
533 //Figure out if the exception is happend due to watch, rwatch or awatch.
534 BreakType
= GetBreakpointType (SystemContext
, BreakpointDetected
);
536 //INFO: rwatch is not supported due to the way IA32 debug registers work
537 if ((BreakType
== DataWrite
) || (BreakType
== DataRead
) || (BreakType
== DataReadWrite
)) {
540 DataAddress
= GetBreakpointDataAddress (SystemContext
, BreakpointDetected
);
542 //Assign appropriate buffer to print particular watchpoint type
543 if (BreakType
== DataWrite
) {
544 WatchStrPtr
= "watch";
545 } else if (BreakType
== DataRead
) {
546 WatchStrPtr
= "rwatch";
547 } else if (BreakType
== DataReadWrite
) {
548 WatchStrPtr
= "awatch";
551 while (*WatchStrPtr
!= '\0') {
552 *TSignalPtr
++ = *WatchStrPtr
++;
557 //Set up series of bytes in big-endian byte order. "awatch" won't work with little-endian byte order.
559 while (RegSize
> 0) {
561 *TSignalPtr
++ = mHexToStr
[(UINT8
)(DataAddress
>> RegSize
) & 0xf];
564 //Always end n:r pair with ';'
572 SendPacket (TSignalBuffer
);
577 Translates the EFI mapping to GDB mapping
579 @param EFIExceptionType EFI Exception that is being processed
580 @retval UINTN that corresponds to EFIExceptionType's GDB exception type number
583 ConvertEFItoGDBtype (
584 IN EFI_EXCEPTION_TYPE EFIExceptionType
589 for (Index
= 0; Index
< MaxEfiException () ; Index
++) {
590 if (gExceptionType
[Index
].Exception
== EFIExceptionType
) {
591 return gExceptionType
[Index
].SignalNo
;
594 return GDB_SIGTRAP
; // this is a GDB trap
599 Find the Length of the area to read and the start addres. Finally, pass them to
600 another function, TransferFromMemToOutBufAndSend, that will read from that memory space and
612 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
]; // the buffer that will hold the address in hex chars
613 CHAR8
*AddrBufPtr
; // pointer to the address buffer
614 CHAR8
*InBufPtr
; /// pointer to the input buffer
616 AddrBufPtr
= AddressBuffer
;
617 InBufPtr
= &PacketData
[1];
618 while (*InBufPtr
!= ',') {
619 *AddrBufPtr
++ = *InBufPtr
++;
623 InBufPtr
++; // this skips ',' in the buffer
626 if (AsciiStrLen (AddressBuffer
) >= MAX_ADDR_SIZE
) {
627 Print((CHAR16
*)L
"Address is too long\n");
628 SendError (GDB_EBADMEMADDRBUFSIZE
);
633 if (AsciiStrLen (PacketData
) - AsciiStrLen (AddressBuffer
) - 2 >= MAX_LENGTH_SIZE
) {
634 Print((CHAR16
*)L
"Length is too long\n");
635 SendError (GDB_EBADMEMLENGTH
);
639 Address
= AsciiStrHexToUintn (AddressBuffer
);
640 Length
= AsciiStrHexToUintn (InBufPtr
);
642 TransferFromMemToOutBufAndSend (Length
, (unsigned char *)Address
);
646 /** "M addr,length :XX..."
647 Find the Length of the area in bytes to write and the start addres. Finally, pass them to
648 another function, TransferFromInBufToMem, that will write to that memory space the info in
660 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
]; // the buffer that will hold the Address in hex chars
661 CHAR8 LengthBuffer
[MAX_LENGTH_SIZE
]; // the buffer that will hold the Length in hex chars
662 CHAR8
*AddrBufPtr
; // pointer to the Address buffer
663 CHAR8
*LengthBufPtr
; // pointer to the Length buffer
664 CHAR8
*InBufPtr
; /// pointer to the input buffer
666 AddrBufPtr
= AddressBuffer
;
667 LengthBufPtr
= LengthBuffer
;
668 InBufPtr
= &PacketData
[1];
670 while (*InBufPtr
!= ',') {
671 *AddrBufPtr
++ = *InBufPtr
++;
675 InBufPtr
++; // this skips ',' in the buffer
677 while (*InBufPtr
!= ':') {
678 *LengthBufPtr
++ = *InBufPtr
++;
680 *LengthBufPtr
= '\0';
682 InBufPtr
++; // this skips ':' in the buffer
684 Address
= AsciiStrHexToUintn (AddressBuffer
);
685 Length
= AsciiStrHexToUintn (LengthBuffer
);
689 //Check if Address is not too long.
690 if (AsciiStrLen (AddressBuffer
) >= MAX_ADDR_SIZE
) {
691 Print ((CHAR16
*)L
"Address too long..\n");
692 SendError (GDB_EBADMEMADDRBUFSIZE
);
696 //Check if message length is not too long
697 if (AsciiStrLen (LengthBuffer
) >= MAX_LENGTH_SIZE
) {
698 Print ((CHAR16
*)L
"Length too long..\n");
699 SendError (GDB_EBADMEMLENGBUFSIZE
);
703 // Check if Message is not too long/short.
704 // 3 = 'M' + ',' + ':'
705 MessageLength
= (AsciiStrLen (PacketData
) - AsciiStrLen (AddressBuffer
) - AsciiStrLen (LengthBuffer
) - 3);
706 if (MessageLength
!= (2*Length
)) {
707 //Message too long/short. New data is not the right size.
708 SendError (GDB_EBADMEMDATASIZE
);
711 TransferFromInBufToMem (Length
, (unsigned char *)Address
, InBufPtr
);
715 Parses breakpoint packet data and captures Breakpoint type, Address and length.
716 In case of an error, function returns particular error code. Returning 0 meaning
719 @param PacketData Pointer to the payload data for the packet.
720 @param Type Breakpoint type
721 @param Address Breakpoint address
722 @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
725 @retval {other} Particular error code
729 ParseBreakpointPacket (
730 IN CHAR8
*PacketData
,
736 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
];
737 CHAR8
*AddressBufferPtr
;
738 CHAR8
*PacketDataPtr
;
740 PacketDataPtr
= &PacketData
[1];
741 AddressBufferPtr
= AddressBuffer
;
743 *Type
= AsciiStrHexToUintn (PacketDataPtr
);
745 //Breakpoint/watchpoint type should be between 0 to 4
747 Print ((CHAR16
*)L
"Type is invalid\n");
748 return 22; //EINVAL: Invalid argument.
751 //Skip ',' in the buffer.
752 while (*PacketDataPtr
++ != ',');
754 //Parse Address information
755 while (*PacketDataPtr
!= ',') {
756 *AddressBufferPtr
++ = *PacketDataPtr
++;
758 *AddressBufferPtr
= '\0';
760 //Check if Address is not too long.
761 if (AsciiStrLen (AddressBuffer
) >= MAX_ADDR_SIZE
) {
762 Print ((CHAR16
*)L
"Address too long..\n");
763 return 40; //EMSGSIZE: Message size too long.
766 *Address
= AsciiStrHexToUintn (AddressBuffer
);
768 PacketDataPtr
++; //This skips , in the buffer
770 //Parse Length information
771 *Length
= AsciiStrHexToUintn (PacketDataPtr
);
773 //Length should be 1, 2 or 4 bytes
775 Print ((CHAR16
*)L
"Length is invalid\n");
776 return 22; //EINVAL: Invalid argument
779 return 0; //0 = No error
783 gXferObjectReadResponse (
788 CHAR8
*OutBufPtr
; // pointer to the output buffer
792 // Response starts with 'm' or 'l' if it is the end
793 OutBufPtr
= gOutBuffer
;
797 // Binary data encoding
798 OutBufPtr
= gOutBuffer
;
799 while (*Str
!= '\0') {
801 if ((Char
== 0x7d) || (Char
== 0x23) || (Char
== 0x24) || (Char
== 0x2a)) {
811 *OutBufPtr
= '\0' ; // the end of the buffer
812 SendPacket (gOutBuffer
);
819 Note: This should be a library function. In the Apple case you have to add
820 the size of the PE/COFF header into the starting address to make things work
821 right as there is no way to pad the Mach-O for the size of the PE/COFF header.
824 Returns a pointer to the PDB file name for a PE/COFF image that has been
825 loaded into system memory with the PE/COFF Loader Library functions.
827 Returns the PDB file name for the PE/COFF image specified by Pe32Data. If
828 the PE/COFF image specified by Pe32Data is not a valid, then NULL is
829 returned. If the PE/COFF image specified by Pe32Data does not contain a
830 debug directory entry, then NULL is returned. If the debug directory entry
831 in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
832 then NULL is returned.
833 If Pe32Data is NULL, then ASSERT().
835 @param Pe32Data Pointer to the PE/COFF image that is loaded in system
837 @param DebugBase Address that the debugger would use as the base of the image
839 @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
840 if it cannot be retrieved. DebugBase is only valid if PDB file name is
846 PeCoffLoaderGetDebuggerInfo (
851 EFI_IMAGE_DOS_HEADER
*DosHdr
;
852 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
853 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
854 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
856 VOID
*CodeViewEntryPointer
;
858 UINT32 NumberOfRvaAndSizes
;
862 ASSERT (Pe32Data
!= NULL
);
865 DirectoryEntry
= NULL
;
867 NumberOfRvaAndSizes
= 0;
870 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
871 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
873 // DOS image header is present, so read the PE header after the DOS image header.
875 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
878 // DOS image header is not present, so PE header is at the image base.
880 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
883 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
884 if (Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
!= 0) {
885 DirectoryEntry
= &Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
];
886 TEImageAdjust
= sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
;
887 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)((UINTN
) Hdr
.Te
+
888 Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
+
891 SizeOfHeaders
= sizeof (EFI_TE_IMAGE_HEADER
) + (UINTN
)Hdr
.Te
->BaseOfCode
- (UINTN
)Hdr
.Te
->StrippedSize
;
893 // __APPLE__ check this math...
894 *DebugBase
= ((CHAR8
*)Pe32Data
) - TEImageAdjust
;
895 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
897 *DebugBase
= Pe32Data
;
901 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
902 // It is due to backward-compatibility, for some system might
903 // generate PE32+ image with PE32 Magic.
905 switch (Hdr
.Pe32
->FileHeader
.Machine
) {
906 case EFI_IMAGE_MACHINE_IA32
:
908 // Assume PE32 image with IA32 Machine field.
910 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
912 case EFI_IMAGE_MACHINE_X64
:
913 case EFI_IMAGE_MACHINE_IA64
:
915 // Assume PE32+ image with X64 or IPF Machine field
917 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
921 // For unknow Machine field, use Magic in optional Header
923 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
926 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
928 // Use PE32 offset get Debug Directory Entry
930 SizeOfHeaders
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
;
931 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
932 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
933 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) Pe32Data
+ DirectoryEntry
->VirtualAddress
);
934 } else if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
936 // Use PE32+ offset get Debug Directory Entry
938 SizeOfHeaders
= Hdr
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
939 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
940 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
941 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) Pe32Data
+ DirectoryEntry
->VirtualAddress
);
944 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
945 DirectoryEntry
= NULL
;
952 if (DebugEntry
== NULL
|| DirectoryEntry
== NULL
) {
956 for (DirCount
= 0; DirCount
< DirectoryEntry
->Size
; DirCount
+= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
), DebugEntry
++) {
957 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
958 if (DebugEntry
->SizeOfData
> 0) {
959 CodeViewEntryPointer
= (VOID
*) ((UINTN
) DebugEntry
->RVA
+ ((UINTN
)Pe32Data
) + (UINTN
)TEImageAdjust
);
960 switch (* (UINT32
*) CodeViewEntryPointer
) {
961 case CODEVIEW_SIGNATURE_NB10
:
962 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
));
963 case CODEVIEW_SIGNATURE_RSDS
:
964 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
));
965 case CODEVIEW_SIGNATURE_MTOC
:
966 *DebugBase
= (VOID
*)(UINTN
)((UINTN
)DebugBase
- SizeOfHeaders
);
967 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY
));
981 Process "qXfer:object:read:annex:offset,length" request.
983 Returns an XML document that contains loaded libraries. In our case it is
984 information in the EFI Debug Image Table converted into an XML document.
986 GDB will call with an arbitrary length (it can't know the real length and
987 will reply with chunks of XML that are easy for us to deal with. Gdb will
988 keep calling until we say we are done. XML doc looks like:
991 <library name="/a/a/c/d.dSYM"><segment address="0x10000000"/></library>
992 <library name="/a/m/e/e.pdb"><segment address="0x20000000"/></library>
993 <library name="/a/l/f/f.dll"><segment address="0x30000000"/></library>
996 Since we can not allocate memory in interrupt context this module has
997 assumptions about how it will get called:
998 1) Length will generally be max remote packet size (big enough)
999 2) First Offset of an XML document read needs to be 0
1000 3) This code will return back small chunks of the XML document on every read.
1001 Each subsequent call will ask for the next available part of the document.
1003 Note: The only variable size element in the XML is:
1004 " <library name=\"%s\"><segment address=\"%p\"/></library>\n" and it is
1005 based on the file path and name of the symbol file. If the symbol file name
1006 is bigger than the max gdb remote packet size we could update this code
1007 to respond back in chunks.
1009 @param Offset offset into special data area
1010 @param Length number of bytes to read starting at Offset
1023 if (Offset
!= gPacketqXferLibraryOffset
) {
1024 SendError (GDB_EINVALIDARG
);
1025 Print (L
"\nqXferLibrary (%d, %d) != %d\n", Offset
, Length
, gPacketqXferLibraryOffset
);
1027 // Force a retry from the beginning
1028 gPacketqXferLibraryOffset
= 0;
1034 gPacketqXferLibraryOffset
+= gXferObjectReadResponse ('m', "<library-list>\n");
1036 // The owner of the table may have had to ralloc it so grab a fresh copy every time
1037 // we assume qXferLibrary will get called over and over again until the entire XML table is
1038 // returned in a tight loop. Since we are in the debugger the table should not get updated
1039 gDebugTable
= gDebugImageTableHeader
->EfiDebugImageInfoTable
;
1040 gEfiDebugImageTableEntry
= 0;
1044 if (gDebugTable
!= NULL
) {
1045 for (; gEfiDebugImageTableEntry
< gDebugImageTableHeader
->TableSize
; gEfiDebugImageTableEntry
++, gDebugTable
++) {
1046 if (gDebugTable
->NormalImage
!= NULL
) {
1047 if ((gDebugTable
->NormalImage
->ImageInfoType
== EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
) &&
1048 (gDebugTable
->NormalImage
->LoadedImageProtocolInstance
!= NULL
)) {
1049 Pdb
= PeCoffLoaderGetDebuggerInfo (
1050 gDebugTable
->NormalImage
->LoadedImageProtocolInstance
->ImageBase
,
1054 Size
= AsciiSPrint (
1056 sizeof (gXferLibraryBuffer
),
1057 " <library name=\"%a\"><segment address=\"0x%p\"/></library>\n",
1061 if ((Size
!= 0) && (Size
!= (sizeof (gXferLibraryBuffer
) - 1))) {
1062 gPacketqXferLibraryOffset
+= gXferObjectReadResponse ('m', gXferLibraryBuffer
);
1064 // Update loop variables so we are in the right place when we get back
1065 gEfiDebugImageTableEntry
++;
1069 // We could handle <library> entires larger than sizeof (gXferLibraryBuffer) here if
1070 // needed by breaking up into N packets
1071 // "<library name=\"%s
1072 // the rest of the string (as many packets as required
1073 // \"><segment address=\"%d\"/></library> (fixed size)
1075 // But right now we just skip any entry that is too big
1084 gXferObjectReadResponse ('l', "</library-list>\n");
1085 gPacketqXferLibraryOffset
= 0;
1091 Exception Hanldler for GDB. It will be called for all exceptions
1092 registered via the gExceptionType[] array.
1094 @param ExceptionType Exception that is being processed
1095 @param SystemContext Register content at time of the exception
1099 GdbExceptionHandler (
1100 IN EFI_EXCEPTION_TYPE ExceptionType
,
1101 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1104 UINT8 GdbExceptionType
;
1108 if (ValidateException (ExceptionType
, SystemContext
) == FALSE
) {
1112 RemoveSingleStep (SystemContext
);
1114 GdbExceptionType
= ConvertEFItoGDBtype (ExceptionType
);
1115 GdbSendTSignal (SystemContext
, GdbExceptionType
);
1118 ReceivePacket (gInBuffer
, MAX_BUF_SIZE
);
1120 switch (gInBuffer
[0]) {
1122 GdbSendTSignal (SystemContext
, GdbExceptionType
);
1126 ContinueAtAddress (SystemContext
, gInBuffer
);
1130 ReadGeneralRegisters (SystemContext
);
1134 WriteGeneralRegisters (SystemContext
, gInBuffer
);
1138 //Return "OK" packet since we don't have more than one thread.
1143 ReadFromMemory (gInBuffer
);
1147 WriteToMemory (gInBuffer
);
1151 WriteNthRegister (SystemContext
, gInBuffer
);
1155 // Still debugging this code. Not used in Darwin
1158 // General Query Packets
1159 if (AsciiStrnCmp (gInBuffer
, "qSupported", 10) == 0) {
1160 // return what we currently support, we don't parse what gdb suports
1161 AsciiSPrint (gOutBuffer
, MAX_BUF_SIZE
, "qXfer:libraries:read+;PacketSize=%d", MAX_BUF_SIZE
);
1162 SendPacket (gOutBuffer
);
1163 } else if (AsciiStrnCmp (gInBuffer
, "qXfer:libraries:read::", 22) == 0) {
1164 // ‘qXfer:libraries:read::offset,length
1165 // gInBuffer[22] is offset string, ++Ptr is length string’
1166 for (Ptr
= &gInBuffer
[22]; *Ptr
!= ','; Ptr
++);
1168 // Not sure if multi-radix support is required. Currently only support decimal
1169 QxferLibrary (AsciiStrHexToUintn (&gInBuffer
[22]), AsciiStrHexToUintn (++Ptr
));
1170 } if (AsciiStrnCmp (gInBuffer
, "qOffsets", 10) == 0) {
1171 AsciiSPrint (gOutBuffer
, MAX_BUF_SIZE
, "Text=1000;Data=f000;Bss=f000");
1172 SendPacket (gOutBuffer
);
1175 SendNotSupported ();
1180 SingleStep (SystemContext
, gInBuffer
);
1184 RemoveBreakPoint (SystemContext
, gInBuffer
);
1188 InsertBreakPoint (SystemContext
, gInBuffer
);
1193 SendNotSupported ();
1201 Periodic callback for GDB. This function is used to catch a ctrl-c or other
1202 break in type command from GDB.
1204 @param SystemContext Register content at time of the call
1208 GdbPeriodicCallBack (
1209 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1213 // gCtrlCBreakFlag may have been set from a previous F response package
1214 // and we set the global as we need to process it at a point where we
1215 // can update the system context. If we are in the middle of processing
1216 // a F Packet it is not safe to read the GDB serial stream so we need
1217 // to skip it on this check
1219 if (!gCtrlCBreakFlag
&& !gProcessingFPacket
) {
1221 // Ctrl-C was not pending so grab any pending characters and see if they
1222 // are a Ctrl-c (0x03). If so set the Ctrl-C global.
1225 if (!GdbIsCharAvailable ()) {
1227 // No characters are pending so exit the loop
1232 if (GdbGetChar () == 0x03) {
1233 gCtrlCBreakFlag
= TRUE
;
1235 // We have a ctrl-c so exit the loop
1242 if (gCtrlCBreakFlag
) {
1244 // Update the context to force a single step trap when we exit the GDB
1245 // stub. This will transfer control to GdbExceptionHandler () and let
1246 // us break into the program. We don't want to break into the GDB stub.
1248 AddSingleStep (SystemContext
);
1249 gCtrlCBreakFlag
= FALSE
;