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 This program and the accompanying materials
11 are licensed and made available under the terms and conditions of the BSD License
12 which accompanies this distribution. The full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include <GdbStubInternal.h>
21 #include <Protocol/DebugPort.h>
24 UINTN gMaxProcessorIndex
= 0;
27 // Buffers for basic gdb communication
29 CHAR8 gInBuffer
[MAX_BUF_SIZE
];
30 CHAR8 gOutBuffer
[MAX_BUF_SIZE
];
32 // Assume gdb does a "qXfer:libraries:read::offset,length" when it connects so we can default
33 // this value to FALSE. Since gdb can reconnect its self a global default is not good enough
34 BOOLEAN gSymbolTableUpdate
= FALSE
;
36 VOID
*gGdbSymbolEventHandlerRegistration
= NULL
;
39 // Globals for returning XML from qXfer:libraries:read packet
41 UINTN gPacketqXferLibraryOffset
= 0;
42 UINTN gEfiDebugImageTableEntry
= 0;
43 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
*gDebugImageTableHeader
= NULL
;
44 EFI_DEBUG_IMAGE_INFO
*gDebugTable
= NULL
;
45 CHAR8 gXferLibraryBuffer
[2000];
47 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexToStr
[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
52 GdbSymbolEventHandler (
61 The user Entry Point for Application. The user code starts with this function
62 as the real entry point for the image goes into a library that calls this
65 @param[in] ImageHandle The firmware allocated handle for the EFI image.
66 @param[in] SystemTable A pointer to the EFI System Table.
68 @retval EFI_SUCCESS The entry point is executed successfully.
69 @retval other Some error occurs when executing this entry point.
75 IN EFI_HANDLE ImageHandle
,
76 IN EFI_SYSTEM_TABLE
*SystemTable
80 EFI_DEBUG_SUPPORT_PROTOCOL
*DebugSupport
;
87 Status
= EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid
, (VOID
**)&gDebugImageTableHeader
);
88 if (EFI_ERROR (Status
)) {
89 gDebugImageTableHeader
= NULL
;
92 Status
= gBS
->LocateHandleBuffer (
94 &gEfiDebugSupportProtocolGuid
,
99 if (EFI_ERROR (Status
)) {
100 DEBUG ((EFI_D_ERROR
, "Debug Support Protocol not found\n"));
106 IsaSupported
= FALSE
;
109 Status
= gBS
->HandleProtocol (
110 Handles
[HandleCount
],
111 &gEfiDebugSupportProtocolGuid
,
112 (VOID
**) &DebugSupport
114 if (!EFI_ERROR (Status
)) {
115 if (CheckIsa (DebugSupport
->Isa
)) {
116 // We found what we are looking for so break out of the loop
121 } while (HandleCount
> 0);
125 DEBUG ((EFI_D_ERROR
, "Debug Support Protocol does not support our ISA\n"));
127 return EFI_NOT_FOUND
;
130 Status
= DebugSupport
->GetMaximumProcessorIndex (DebugSupport
, &gMaxProcessorIndex
);
131 ASSERT_EFI_ERROR (Status
);
133 DEBUG ((EFI_D_INFO
, "Debug Support Protocol ISA %x\n", DebugSupport
->Isa
));
134 DEBUG ((EFI_D_INFO
, "Debug Support Protocol Processor Index %d\n", gMaxProcessorIndex
));
136 // Call processor-specific init routine
137 InitializeProcessor ();
139 for (Processor
= 0; Processor
<= gMaxProcessorIndex
; Processor
++) {
140 for (Index
= 0; Index
< MaxEfiException (); Index
++) {
141 Status
= DebugSupport
->RegisterExceptionCallback (DebugSupport
, Processor
, GdbExceptionHandler
, gExceptionType
[Index
].Exception
);
142 ASSERT_EFI_ERROR (Status
);
145 // Current edk2 DebugPort is not interrupt context safe so we can not use it
147 Status
= DebugSupport
->RegisterPeriodicCallback (DebugSupport
, Processor
, GdbPeriodicCallBack
);
148 ASSERT_EFI_ERROR (Status
);
152 // This even fires every time an image is added. This allows the stub to know when gdb needs
153 // to update the symbol table.
155 Status
= gBS
->CreateEvent (
158 GdbSymbolEventHandler
,
162 ASSERT_EFI_ERROR (Status
);
165 // Register for protocol notifications on this event
167 Status
= gBS
->RegisterProtocolNotify (
168 &gEfiLoadedImageProtocolGuid
,
170 &gGdbSymbolEventHandlerRegistration
172 ASSERT_EFI_ERROR (Status
);
175 if (PcdGetBool (PcdGdbSerial
)) {
176 GdbInitializeSerialConsole ();
183 Transfer length bytes of input buffer, starting at Address, to memory.
185 @param length the number of the bytes to be transferred/written
186 @param *address the start address of the transferring/writing the memory
187 @param *new_data the new data to be written to memory
191 TransferFromInBufToMem (
193 IN
unsigned char *Address
,
200 while (Length
-- > 0) {
201 c1
= (CHAR8
)HexCharToInt (*NewData
++);
202 c2
= (CHAR8
)HexCharToInt (*NewData
++);
204 if ((c1
< 0) || (c2
< 0)) {
205 Print ((CHAR16
*)L
"Bad message from write to memory..\n");
206 SendError (GDB_EBADMEMDATA
);
209 *Address
++ = (UINT8
)((c1
<< 4) + c2
);
217 Transfer Length bytes of memory starting at Address to an output buffer, OutBuffer. This function will finally send the buffer
220 @param Length the number of the bytes to be transferred/read
221 @param *address pointer to the start address of the transferring/reading the memory
225 TransferFromMemToOutBufAndSend (
227 IN
unsigned char *Address
230 // there are Length bytes and every byte is represented as 2 hex chars
231 CHAR8 OutBuffer
[MAX_BUF_SIZE
];
232 CHAR8
*OutBufPtr
; // pointer to the output buffer
235 if (ValidateAddress(Address
) == FALSE
) {
240 OutBufPtr
= OutBuffer
;
243 Char
= mHexToStr
[*Address
>> 4];
244 if ((Char
>= 'A') && (Char
<= 'F')) {
245 Char
= Char
- 'A' + 'a';
249 Char
= mHexToStr
[*Address
& 0x0f];
250 if ((Char
>= 'A') && (Char
<= 'F')) {
251 Char
= Char
- 'A' + 'a';
259 *OutBufPtr
= '\0' ; // the end of the buffer
260 SendPacket (OutBuffer
);
266 Send a GDB Remote Serial Protocol Packet
268 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
269 the packet teminating character '#' and the two digit checksum.
271 If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up
272 in an infinit loop. This is so if you unplug the debugger code just keeps running
274 @param PacketData Payload data for the packet
277 @retval Number of bytes of packet data sent.
291 Timeout
= PcdGet32 (PcdGdbMaxPacketRetryCount
);
298 if (Timeout
-- == 0) {
299 // Only try a finite number of times so we don't get stuck in the loop
306 for (CheckSum
= 0, Count
=0 ; *Ptr
!= '\0'; Ptr
++, Count
++) {
308 CheckSum
= CheckSum
+ *Ptr
;
311 // Packet terminating character and checksum
313 GdbPutChar (mHexToStr
[CheckSum
>> 4]);
314 GdbPutChar (mHexToStr
[CheckSum
& 0x0F]);
316 TestChar
= GdbGetChar ();
317 } while (TestChar
!= '+');
323 Receive a GDB Remote Serial Protocol Packet
325 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
326 the packet teminating character '#' and the two digit checksum.
328 If host re-starts sending a packet without ending the previous packet, only the last valid packet is processed.
329 (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)
331 If an ack '+' is not sent resend the packet
333 @param PacketData Payload data for the packet
335 @retval Number of bytes of packet data received.
340 OUT CHAR8
*PacketData
,
341 IN UINTN PacketDataSize
350 ZeroMem (PacketData
, PacketDataSize
);
353 // wait for the start of a packet
354 TestChar
= GdbGetChar ();
355 while (TestChar
!= '$') {
356 TestChar
= GdbGetChar ();
360 for (Index
= 0, CheckSum
= 0; Index
< (PacketDataSize
- 1); Index
++) {
361 Char
= GdbGetChar ();
369 PacketData
[Index
] = Char
;
370 CheckSum
= CheckSum
+ Char
;
372 PacketData
[Index
] = '\0';
374 if (Index
== PacketDataSize
) {
378 SumString
[0] = GdbGetChar ();
379 SumString
[1] = GdbGetChar ();
382 if (AsciiStrHexToUintn (SumString
) == CheckSum
) {
386 // Null terminate the callers string
387 PacketData
[Index
] = '\0';
400 Empties the given buffer
401 @param Buf pointer to the first element in buffer to be emptied
413 Converts an 8-bit Hex Char into a INTN.
415 @param Char the hex character to be converted into UINTN
416 @retval a INTN, from 0 to 15, that corressponds to Char
417 -1 if Char is not a hex character
424 if ((Char
>= 'A') && (Char
<= 'F')) {
425 return Char
- 'A' + 10;
426 } else if ((Char
>= 'a') && (Char
<= 'f')) {
427 return Char
- 'a' + 10;
428 } else if ((Char
>= '0') && (Char
<= '9')) {
430 } else { // if not a hex value, return a negative value
435 // 'E' + the biggest error number is 255, so its 2 hex digits + buffer end
436 CHAR8
*gError
= "E__";
439 Send an error with the given error number after converting to hex.
440 The error number is put into the buffer in hex. '255' is the biggest errno we can send.
441 ex: 162 will be sent as A2.
443 @param errno the error number that will be sent
452 // Replace _, or old data, with current errno
454 gError
[1] = mHexToStr
[ErrorNum
>> 4];
455 gError
[2] = mHexToStr
[ErrorNum
& 0x0f];
457 SendPacket (gError
); // send buffer
463 Send 'OK' when the function is done executing successfully.
471 SendPacket ("OK"); // send buffer
476 Send empty packet to specify that particular command/functionality is not supported.
489 Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints
491 @param SystemContext Register content at time of the exception
492 @param GdbExceptionType GDB exception type
496 IN EFI_SYSTEM_CONTEXT SystemContext
,
497 IN UINT8 GdbExceptionType
500 CHAR8 TSignalBuffer
[128];
502 UINTN BreakpointDetected
;
503 BREAK_TYPE BreakType
;
505 CHAR8
*WatchStrPtr
= NULL
;
508 TSignalPtr
= &TSignalBuffer
[0];
510 //Construct TSignal packet
514 // replace _, or previous value, with Exception type
516 *TSignalPtr
++ = mHexToStr
[GdbExceptionType
>> 4];
517 *TSignalPtr
++ = mHexToStr
[GdbExceptionType
& 0x0f];
519 if (GdbExceptionType
== GDB_SIGTRAP
) {
520 if (gSymbolTableUpdate
) {
522 // We can only send back on reason code. So if the flag is set it means the breakpoint is from our event handler
524 WatchStrPtr
= "library:;";
525 while (*WatchStrPtr
!= '\0') {
526 *TSignalPtr
++ = *WatchStrPtr
++;
528 gSymbolTableUpdate
= FALSE
;
533 // possible n:r pairs
536 //Retrieve the breakpoint number
537 BreakpointDetected
= GetBreakpointDetected (SystemContext
);
539 //Figure out if the exception is happend due to watch, rwatch or awatch.
540 BreakType
= GetBreakpointType (SystemContext
, BreakpointDetected
);
542 //INFO: rwatch is not supported due to the way IA32 debug registers work
543 if ((BreakType
== DataWrite
) || (BreakType
== DataRead
) || (BreakType
== DataReadWrite
)) {
546 DataAddress
= GetBreakpointDataAddress (SystemContext
, BreakpointDetected
);
548 //Assign appropriate buffer to print particular watchpoint type
549 if (BreakType
== DataWrite
) {
550 WatchStrPtr
= "watch";
551 } else if (BreakType
== DataRead
) {
552 WatchStrPtr
= "rwatch";
553 } else if (BreakType
== DataReadWrite
) {
554 WatchStrPtr
= "awatch";
557 while (*WatchStrPtr
!= '\0') {
558 *TSignalPtr
++ = *WatchStrPtr
++;
563 //Set up series of bytes in big-endian byte order. "awatch" won't work with little-endian byte order.
565 while (RegSize
> 0) {
567 *TSignalPtr
++ = mHexToStr
[(UINT8
)(DataAddress
>> RegSize
) & 0xf];
570 //Always end n:r pair with ';'
578 SendPacket (TSignalBuffer
);
583 Translates the EFI mapping to GDB mapping
585 @param EFIExceptionType EFI Exception that is being processed
586 @retval UINTN that corresponds to EFIExceptionType's GDB exception type number
589 ConvertEFItoGDBtype (
590 IN EFI_EXCEPTION_TYPE EFIExceptionType
595 for (Index
= 0; Index
< MaxEfiException () ; Index
++) {
596 if (gExceptionType
[Index
].Exception
== EFIExceptionType
) {
597 return gExceptionType
[Index
].SignalNo
;
600 return GDB_SIGTRAP
; // this is a GDB trap
605 Find the Length of the area to read and the start addres. Finally, pass them to
606 another function, TransferFromMemToOutBufAndSend, that will read from that memory space and
618 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
]; // the buffer that will hold the address in hex chars
619 CHAR8
*AddrBufPtr
; // pointer to the address buffer
620 CHAR8
*InBufPtr
; /// pointer to the input buffer
622 AddrBufPtr
= AddressBuffer
;
623 InBufPtr
= &PacketData
[1];
624 while (*InBufPtr
!= ',') {
625 *AddrBufPtr
++ = *InBufPtr
++;
629 InBufPtr
++; // this skips ',' in the buffer
632 if (AsciiStrLen (AddressBuffer
) >= MAX_ADDR_SIZE
) {
633 Print((CHAR16
*)L
"Address is too long\n");
634 SendError (GDB_EBADMEMADDRBUFSIZE
);
639 if (AsciiStrLen (PacketData
) - AsciiStrLen (AddressBuffer
) - 2 >= MAX_LENGTH_SIZE
) {
640 Print((CHAR16
*)L
"Length is too long\n");
641 SendError (GDB_EBADMEMLENGTH
);
645 Address
= AsciiStrHexToUintn (AddressBuffer
);
646 Length
= AsciiStrHexToUintn (InBufPtr
);
648 TransferFromMemToOutBufAndSend (Length
, (unsigned char *)Address
);
652 /** "M addr,length :XX..."
653 Find the Length of the area in bytes to write and the start addres. Finally, pass them to
654 another function, TransferFromInBufToMem, that will write to that memory space the info in
666 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
]; // the buffer that will hold the Address in hex chars
667 CHAR8 LengthBuffer
[MAX_LENGTH_SIZE
]; // the buffer that will hold the Length in hex chars
668 CHAR8
*AddrBufPtr
; // pointer to the Address buffer
669 CHAR8
*LengthBufPtr
; // pointer to the Length buffer
670 CHAR8
*InBufPtr
; /// pointer to the input buffer
672 AddrBufPtr
= AddressBuffer
;
673 LengthBufPtr
= LengthBuffer
;
674 InBufPtr
= &PacketData
[1];
676 while (*InBufPtr
!= ',') {
677 *AddrBufPtr
++ = *InBufPtr
++;
681 InBufPtr
++; // this skips ',' in the buffer
683 while (*InBufPtr
!= ':') {
684 *LengthBufPtr
++ = *InBufPtr
++;
686 *LengthBufPtr
= '\0';
688 InBufPtr
++; // this skips ':' in the buffer
690 Address
= AsciiStrHexToUintn (AddressBuffer
);
691 Length
= AsciiStrHexToUintn (LengthBuffer
);
695 //Check if Address is not too long.
696 if (AsciiStrLen (AddressBuffer
) >= MAX_ADDR_SIZE
) {
697 Print ((CHAR16
*)L
"Address too long..\n");
698 SendError (GDB_EBADMEMADDRBUFSIZE
);
702 //Check if message length is not too long
703 if (AsciiStrLen (LengthBuffer
) >= MAX_LENGTH_SIZE
) {
704 Print ((CHAR16
*)L
"Length too long..\n");
705 SendError (GDB_EBADMEMLENGBUFSIZE
);
709 // Check if Message is not too long/short.
710 // 3 = 'M' + ',' + ':'
711 MessageLength
= (AsciiStrLen (PacketData
) - AsciiStrLen (AddressBuffer
) - AsciiStrLen (LengthBuffer
) - 3);
712 if (MessageLength
!= (2*Length
)) {
713 //Message too long/short. New data is not the right size.
714 SendError (GDB_EBADMEMDATASIZE
);
717 TransferFromInBufToMem (Length
, (unsigned char *)Address
, InBufPtr
);
721 Parses breakpoint packet data and captures Breakpoint type, Address and length.
722 In case of an error, function returns particular error code. Returning 0 meaning
725 @param PacketData Pointer to the payload data for the packet.
726 @param Type Breakpoint type
727 @param Address Breakpoint address
728 @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
731 @retval {other} Particular error code
735 ParseBreakpointPacket (
736 IN CHAR8
*PacketData
,
742 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
];
743 CHAR8
*AddressBufferPtr
;
744 CHAR8
*PacketDataPtr
;
746 PacketDataPtr
= &PacketData
[1];
747 AddressBufferPtr
= AddressBuffer
;
749 *Type
= AsciiStrHexToUintn (PacketDataPtr
);
751 //Breakpoint/watchpoint type should be between 0 to 4
753 Print ((CHAR16
*)L
"Type is invalid\n");
754 return 22; //EINVAL: Invalid argument.
757 //Skip ',' in the buffer.
758 while (*PacketDataPtr
++ != ',');
760 //Parse Address information
761 while (*PacketDataPtr
!= ',') {
762 *AddressBufferPtr
++ = *PacketDataPtr
++;
764 *AddressBufferPtr
= '\0';
766 //Check if Address is not too long.
767 if (AsciiStrLen (AddressBuffer
) >= MAX_ADDR_SIZE
) {
768 Print ((CHAR16
*)L
"Address too long..\n");
769 return 40; //EMSGSIZE: Message size too long.
772 *Address
= AsciiStrHexToUintn (AddressBuffer
);
774 PacketDataPtr
++; //This skips , in the buffer
776 //Parse Length information
777 *Length
= AsciiStrHexToUintn (PacketDataPtr
);
779 //Length should be 1, 2 or 4 bytes
781 Print ((CHAR16
*)L
"Length is invalid\n");
782 return 22; //EINVAL: Invalid argument
785 return 0; //0 = No error
789 gXferObjectReadResponse (
794 CHAR8
*OutBufPtr
; // pointer to the output buffer
798 // Response starts with 'm' or 'l' if it is the end
799 OutBufPtr
= gOutBuffer
;
803 // Binary data encoding
804 OutBufPtr
= gOutBuffer
;
805 while (*Str
!= '\0') {
807 if ((Char
== 0x7d) || (Char
== 0x23) || (Char
== 0x24) || (Char
== 0x2a)) {
817 *OutBufPtr
= '\0' ; // the end of the buffer
818 SendPacket (gOutBuffer
);
825 Note: This should be a library function. In the Apple case you have to add
826 the size of the PE/COFF header into the starting address to make things work
827 right as there is no way to pad the Mach-O for the size of the PE/COFF header.
830 Returns a pointer to the PDB file name for a PE/COFF image that has been
831 loaded into system memory with the PE/COFF Loader Library functions.
833 Returns the PDB file name for the PE/COFF image specified by Pe32Data. If
834 the PE/COFF image specified by Pe32Data is not a valid, then NULL is
835 returned. If the PE/COFF image specified by Pe32Data does not contain a
836 debug directory entry, then NULL is returned. If the debug directory entry
837 in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
838 then NULL is returned.
839 If Pe32Data is NULL, then ASSERT().
841 @param Pe32Data Pointer to the PE/COFF image that is loaded in system
843 @param DebugBase Address that the debugger would use as the base of the image
845 @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
846 if it cannot be retrieved. DebugBase is only valid if PDB file name is
852 PeCoffLoaderGetDebuggerInfo (
857 EFI_IMAGE_DOS_HEADER
*DosHdr
;
858 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
859 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
860 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
862 VOID
*CodeViewEntryPointer
;
864 UINT32 NumberOfRvaAndSizes
;
868 ASSERT (Pe32Data
!= NULL
);
871 DirectoryEntry
= NULL
;
873 NumberOfRvaAndSizes
= 0;
876 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
877 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
879 // DOS image header is present, so read the PE header after the DOS image header.
881 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
884 // DOS image header is not present, so PE header is at the image base.
886 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
889 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
890 if (Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
!= 0) {
891 DirectoryEntry
= &Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
];
892 TEImageAdjust
= sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
;
893 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)((UINTN
) Hdr
.Te
+
894 Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
+
897 SizeOfHeaders
= sizeof (EFI_TE_IMAGE_HEADER
) + (UINTN
)Hdr
.Te
->BaseOfCode
- (UINTN
)Hdr
.Te
->StrippedSize
;
899 // __APPLE__ check this math...
900 *DebugBase
= ((CHAR8
*)Pe32Data
) - TEImageAdjust
;
901 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
903 *DebugBase
= Pe32Data
;
907 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
908 // It is due to backward-compatibility, for some system might
909 // generate PE32+ image with PE32 Magic.
911 switch (Hdr
.Pe32
->FileHeader
.Machine
) {
912 case EFI_IMAGE_MACHINE_IA32
:
914 // Assume PE32 image with IA32 Machine field.
916 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
918 case EFI_IMAGE_MACHINE_X64
:
919 case EFI_IMAGE_MACHINE_IA64
:
921 // Assume PE32+ image with X64 or IPF Machine field
923 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
927 // For unknow Machine field, use Magic in optional Header
929 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
932 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
934 // Use PE32 offset get Debug Directory Entry
936 SizeOfHeaders
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
;
937 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
938 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
939 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) Pe32Data
+ DirectoryEntry
->VirtualAddress
);
940 } else if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
942 // Use PE32+ offset get Debug Directory Entry
944 SizeOfHeaders
= Hdr
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
945 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
946 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
947 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) Pe32Data
+ DirectoryEntry
->VirtualAddress
);
950 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
951 DirectoryEntry
= NULL
;
958 if (DebugEntry
== NULL
|| DirectoryEntry
== NULL
) {
962 for (DirCount
= 0; DirCount
< DirectoryEntry
->Size
; DirCount
+= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
), DebugEntry
++) {
963 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
964 if (DebugEntry
->SizeOfData
> 0) {
965 CodeViewEntryPointer
= (VOID
*) ((UINTN
) DebugEntry
->RVA
+ ((UINTN
)Pe32Data
) + (UINTN
)TEImageAdjust
);
966 switch (* (UINT32
*) CodeViewEntryPointer
) {
967 case CODEVIEW_SIGNATURE_NB10
:
968 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
));
969 case CODEVIEW_SIGNATURE_RSDS
:
970 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
));
971 case CODEVIEW_SIGNATURE_MTOC
:
972 *DebugBase
= (VOID
*)(UINTN
)((UINTN
)DebugBase
- SizeOfHeaders
);
973 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY
));
987 Process "qXfer:object:read:annex:offset,length" request.
989 Returns an XML document that contains loaded libraries. In our case it is
990 information in the EFI Debug Image Table converted into an XML document.
992 GDB will call with an arbitrary length (it can't know the real length and
993 will reply with chunks of XML that are easy for us to deal with. Gdb will
994 keep calling until we say we are done. XML doc looks like:
997 <library name="/a/a/c/d.dSYM"><segment address="0x10000000"/></library>
998 <library name="/a/m/e/e.pdb"><segment address="0x20000000"/></library>
999 <library name="/a/l/f/f.dll"><segment address="0x30000000"/></library>
1002 Since we can not allocate memory in interrupt context this module has
1003 assumptions about how it will get called:
1004 1) Length will generally be max remote packet size (big enough)
1005 2) First Offset of an XML document read needs to be 0
1006 3) This code will return back small chunks of the XML document on every read.
1007 Each subsequent call will ask for the next available part of the document.
1009 Note: The only variable size element in the XML is:
1010 " <library name=\"%s\"><segment address=\"%p\"/></library>\n" and it is
1011 based on the file path and name of the symbol file. If the symbol file name
1012 is bigger than the max gdb remote packet size we could update this code
1013 to respond back in chunks.
1015 @param Offset offset into special data area
1016 @param Length number of bytes to read starting at Offset
1029 if (Offset
!= gPacketqXferLibraryOffset
) {
1030 SendError (GDB_EINVALIDARG
);
1031 Print (L
"\nqXferLibrary (%d, %d) != %d\n", Offset
, Length
, gPacketqXferLibraryOffset
);
1033 // Force a retry from the beginning
1034 gPacketqXferLibraryOffset
= 0;
1040 gPacketqXferLibraryOffset
+= gXferObjectReadResponse ('m', "<library-list>\n");
1042 // The owner of the table may have had to ralloc it so grab a fresh copy every time
1043 // we assume qXferLibrary will get called over and over again until the entire XML table is
1044 // returned in a tight loop. Since we are in the debugger the table should not get updated
1045 gDebugTable
= gDebugImageTableHeader
->EfiDebugImageInfoTable
;
1046 gEfiDebugImageTableEntry
= 0;
1050 if (gDebugTable
!= NULL
) {
1051 for (; gEfiDebugImageTableEntry
< gDebugImageTableHeader
->TableSize
; gEfiDebugImageTableEntry
++, gDebugTable
++) {
1052 if (gDebugTable
->NormalImage
!= NULL
) {
1053 if ((gDebugTable
->NormalImage
->ImageInfoType
== EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
) &&
1054 (gDebugTable
->NormalImage
->LoadedImageProtocolInstance
!= NULL
)) {
1055 Pdb
= PeCoffLoaderGetDebuggerInfo (
1056 gDebugTable
->NormalImage
->LoadedImageProtocolInstance
->ImageBase
,
1060 Size
= AsciiSPrint (
1062 sizeof (gXferLibraryBuffer
),
1063 " <library name=\"%a\"><segment address=\"0x%p\"/></library>\n",
1067 if ((Size
!= 0) && (Size
!= (sizeof (gXferLibraryBuffer
) - 1))) {
1068 gPacketqXferLibraryOffset
+= gXferObjectReadResponse ('m', gXferLibraryBuffer
);
1070 // Update loop variables so we are in the right place when we get back
1071 gEfiDebugImageTableEntry
++;
1075 // We could handle <library> entires larger than sizeof (gXferLibraryBuffer) here if
1076 // needed by breaking up into N packets
1077 // "<library name=\"%s
1078 // the rest of the string (as many packets as required
1079 // \"><segment address=\"%d\"/></library> (fixed size)
1081 // But right now we just skip any entry that is too big
1090 gXferObjectReadResponse ('l', "</library-list>\n");
1091 gPacketqXferLibraryOffset
= 0;
1097 Exception Hanldler for GDB. It will be called for all exceptions
1098 registered via the gExceptionType[] array.
1100 @param ExceptionType Exception that is being processed
1101 @param SystemContext Register content at time of the exception
1105 GdbExceptionHandler (
1106 IN EFI_EXCEPTION_TYPE ExceptionType
,
1107 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1110 UINT8 GdbExceptionType
;
1114 if (ValidateException (ExceptionType
, SystemContext
) == FALSE
) {
1118 RemoveSingleStep (SystemContext
);
1120 GdbExceptionType
= ConvertEFItoGDBtype (ExceptionType
);
1121 GdbSendTSignal (SystemContext
, GdbExceptionType
);
1124 ReceivePacket (gInBuffer
, MAX_BUF_SIZE
);
1126 switch (gInBuffer
[0]) {
1128 GdbSendTSignal (SystemContext
, GdbExceptionType
);
1132 ContinueAtAddress (SystemContext
, gInBuffer
);
1136 ReadGeneralRegisters (SystemContext
);
1140 WriteGeneralRegisters (SystemContext
, gInBuffer
);
1144 //Return "OK" packet since we don't have more than one thread.
1149 ReadFromMemory (gInBuffer
);
1153 WriteToMemory (gInBuffer
);
1157 WriteNthRegister (SystemContext
, gInBuffer
);
1161 // Still debugging this code. Not used in Darwin
1164 // General Query Packets
1165 if (AsciiStrnCmp (gInBuffer
, "qSupported", 10) == 0) {
1166 // return what we currently support, we don't parse what gdb suports
1167 AsciiSPrint (gOutBuffer
, MAX_BUF_SIZE
, "qXfer:libraries:read+;PacketSize=%d", MAX_BUF_SIZE
);
1168 SendPacket (gOutBuffer
);
1169 } else if (AsciiStrnCmp (gInBuffer
, "qXfer:libraries:read::", 22) == 0) {
1170 // ‘qXfer:libraries:read::offset,length
1171 // gInBuffer[22] is offset string, ++Ptr is length string’
1172 for (Ptr
= &gInBuffer
[22]; *Ptr
!= ','; Ptr
++);
1174 // Not sure if multi-radix support is required. Currently only support decimal
1175 QxferLibrary (AsciiStrHexToUintn (&gInBuffer
[22]), AsciiStrHexToUintn (++Ptr
));
1176 } if (AsciiStrnCmp (gInBuffer
, "qOffsets", 10) == 0) {
1177 AsciiSPrint (gOutBuffer
, MAX_BUF_SIZE
, "Text=1000;Data=f000;Bss=f000");
1178 SendPacket (gOutBuffer
);
1181 SendNotSupported ();
1186 SingleStep (SystemContext
, gInBuffer
);
1190 RemoveBreakPoint (SystemContext
, gInBuffer
);
1194 InsertBreakPoint (SystemContext
, gInBuffer
);
1199 SendNotSupported ();
1207 Periodic callback for GDB. This function is used to catch a ctrl-c or other
1208 break in type command from GDB.
1210 @param SystemContext Register content at time of the call
1214 GdbPeriodicCallBack (
1215 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1219 // gCtrlCBreakFlag may have been set from a previous F response package
1220 // and we set the global as we need to process it at a point where we
1221 // can update the system context. If we are in the middle of processing
1222 // a F Packet it is not safe to read the GDB serial stream so we need
1223 // to skip it on this check
1225 if (!gCtrlCBreakFlag
&& !gProcessingFPacket
) {
1227 // Ctrl-C was not pending so grab any pending characters and see if they
1228 // are a Ctrl-c (0x03). If so set the Ctrl-C global.
1231 if (!GdbIsCharAvailable ()) {
1233 // No characters are pending so exit the loop
1238 if (GdbGetChar () == 0x03) {
1239 gCtrlCBreakFlag
= TRUE
;
1241 // We have a ctrl-c so exit the loop
1248 if (gCtrlCBreakFlag
) {
1250 // Update the context to force a single step trap when we exit the GDB
1251 // stub. This will transfer control to GdbExceptionHandler () and let
1252 // us break into the program. We don't want to break into the GDB stub.
1254 AddSingleStep (SystemContext
);
1255 gCtrlCBreakFlag
= FALSE
;