]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/GdbStub/GdbStub.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / EmbeddedPkg / GdbStub / GdbStub.c
1 /** @file
2 UEFI driver that implements a GDB stub
3
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, ...
6
7
8 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
9
10 SPDX-License-Identifier: BSD-2-Clause-Patent
11
12 **/
13
14 #include <GdbStubInternal.h>
15 #include <Protocol/DebugPort.h>
16
17 UINTN gMaxProcessorIndex = 0;
18
19 //
20 // Buffers for basic gdb communication
21 //
22 CHAR8 gInBuffer[MAX_BUF_SIZE];
23 CHAR8 gOutBuffer[MAX_BUF_SIZE];
24
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;
28 EFI_EVENT gEvent;
29 VOID *gGdbSymbolEventHandlerRegistration = NULL;
30
31 //
32 // Globals for returning XML from qXfer:libraries:read packet
33 //
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];
39
40 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexToStr[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
41
42 VOID
43 EFIAPI
44 GdbSymbolEventHandler (
45 IN EFI_EVENT Event,
46 IN VOID *Context
47 )
48 {
49 }
50
51 /**
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
54 function.
55
56 @param[in] ImageHandle The firmware allocated handle for the EFI image.
57 @param[in] SystemTable A pointer to the EFI System Table.
58
59 @retval EFI_SUCCESS The entry point is executed successfully.
60 @retval other Some error occurs when executing this entry point.
61
62 **/
63 EFI_STATUS
64 EFIAPI
65 GdbStubEntry (
66 IN EFI_HANDLE ImageHandle,
67 IN EFI_SYSTEM_TABLE *SystemTable
68 )
69 {
70 EFI_STATUS Status;
71 EFI_DEBUG_SUPPORT_PROTOCOL *DebugSupport;
72 UINTN HandleCount;
73 EFI_HANDLE *Handles;
74 UINTN Index;
75 UINTN Processor;
76 BOOLEAN IsaSupported;
77
78 Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&gDebugImageTableHeader);
79 if (EFI_ERROR (Status)) {
80 gDebugImageTableHeader = NULL;
81 }
82
83 Status = gBS->LocateHandleBuffer (
84 ByProtocol,
85 &gEfiDebugSupportProtocolGuid,
86 NULL,
87 &HandleCount,
88 &Handles
89 );
90 if (EFI_ERROR (Status)) {
91 DEBUG ((DEBUG_ERROR, "Debug Support Protocol not found\n"));
92
93 return Status;
94 }
95
96 DebugSupport = NULL;
97 IsaSupported = FALSE;
98 do {
99 HandleCount--;
100 Status = gBS->HandleProtocol (
101 Handles[HandleCount],
102 &gEfiDebugSupportProtocolGuid,
103 (VOID **)&DebugSupport
104 );
105 if (!EFI_ERROR (Status)) {
106 if (CheckIsa (DebugSupport->Isa)) {
107 // We found what we are looking for so break out of the loop
108 IsaSupported = TRUE;
109 break;
110 }
111 }
112 } while (HandleCount > 0);
113
114 FreePool (Handles);
115
116 if (!IsaSupported) {
117 DEBUG ((DEBUG_ERROR, "Debug Support Protocol does not support our ISA\n"));
118
119 return EFI_NOT_FOUND;
120 }
121
122 Status = DebugSupport->GetMaximumProcessorIndex (DebugSupport, &gMaxProcessorIndex);
123 ASSERT_EFI_ERROR (Status);
124
125 DEBUG ((DEBUG_INFO, "Debug Support Protocol ISA %x\n", DebugSupport->Isa));
126 DEBUG ((DEBUG_INFO, "Debug Support Protocol Processor Index %d\n", gMaxProcessorIndex));
127
128 // Call processor-specific init routine
129 InitializeProcessor ();
130
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);
135 }
136
137 //
138 // Current edk2 DebugPort is not interrupt context safe so we can not use it
139 //
140 Status = DebugSupport->RegisterPeriodicCallback (DebugSupport, Processor, GdbPeriodicCallBack);
141 ASSERT_EFI_ERROR (Status);
142 }
143
144 //
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.
147 //
148 Status = gBS->CreateEvent (
149 EVT_NOTIFY_SIGNAL,
150 TPL_CALLBACK,
151 GdbSymbolEventHandler,
152 NULL,
153 &gEvent
154 );
155 ASSERT_EFI_ERROR (Status);
156
157 //
158 // Register for protocol notifications on this event
159 //
160 Status = gBS->RegisterProtocolNotify (
161 &gEfiLoadedImageProtocolGuid,
162 gEvent,
163 &gGdbSymbolEventHandlerRegistration
164 );
165 ASSERT_EFI_ERROR (Status);
166
167 if (PcdGetBool (PcdGdbSerial)) {
168 GdbInitializeSerialConsole ();
169 }
170
171 return EFI_SUCCESS;
172 }
173
174 /**
175 Transfer length bytes of input buffer, starting at Address, to memory.
176
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
180 **/
181 VOID
182 TransferFromInBufToMem (
183 IN UINTN Length,
184 IN unsigned char *Address,
185 IN CHAR8 *NewData
186 )
187 {
188 CHAR8 c1;
189 CHAR8 c2;
190
191 while (Length-- > 0) {
192 c1 = (CHAR8)HexCharToInt (*NewData++);
193 c2 = (CHAR8)HexCharToInt (*NewData++);
194
195 if ((c1 < 0) || (c2 < 0)) {
196 Print ((CHAR16 *)L"Bad message from write to memory..\n");
197 SendError (GDB_EBADMEMDATA);
198 return;
199 }
200
201 *Address++ = (UINT8)((c1 << 4) + c2);
202 }
203
204 SendSuccess ();
205 }
206
207 /**
208 Transfer Length bytes of memory starting at Address to an output buffer, OutBuffer. This function will finally send the buffer
209 as a packet.
210
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
213 **/
214 VOID
215 TransferFromMemToOutBufAndSend (
216 IN UINTN Length,
217 IN unsigned char *Address
218 )
219 {
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
223 CHAR8 Char;
224
225 if (ValidateAddress (Address) == FALSE) {
226 SendError (14);
227 return;
228 }
229
230 OutBufPtr = OutBuffer;
231 while (Length > 0) {
232 Char = mHexToStr[*Address >> 4];
233 if ((Char >= 'A') && (Char <= 'F')) {
234 Char = Char - 'A' + 'a';
235 }
236
237 *OutBufPtr++ = Char;
238
239 Char = mHexToStr[*Address & 0x0f];
240 if ((Char >= 'A') && (Char <= 'F')) {
241 Char = Char - 'A' + 'a';
242 }
243
244 *OutBufPtr++ = Char;
245
246 Address++;
247 Length--;
248 }
249
250 *OutBufPtr = '\0'; // the end of the buffer
251 SendPacket (OutBuffer);
252 }
253
254 /**
255 Send a GDB Remote Serial Protocol Packet
256
257 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
258 the packet terminating character '#' and the two digit checksum.
259
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
262
263 @param PacketData Payload data for the packet
264
265
266 @retval Number of bytes of packet data sent.
267
268 **/
269 UINTN
270 SendPacket (
271 IN CHAR8 *PacketData
272 )
273 {
274 UINT8 CheckSum;
275 UINTN Timeout;
276 CHAR8 *Ptr;
277 CHAR8 TestChar;
278 UINTN Count;
279
280 Timeout = PcdGet32 (PcdGdbMaxPacketRetryCount);
281
282 Count = 0;
283 do {
284 Ptr = PacketData;
285
286 if (Timeout-- == 0) {
287 // Only try a finite number of times so we don't get stuck in the loop
288 return Count;
289 }
290
291 // Packet prefix
292 GdbPutChar ('$');
293
294 for (CheckSum = 0, Count = 0; *Ptr != '\0'; Ptr++, Count++) {
295 GdbPutChar (*Ptr);
296 CheckSum = CheckSum + *Ptr;
297 }
298
299 // Packet terminating character and checksum
300 GdbPutChar ('#');
301 GdbPutChar (mHexToStr[CheckSum >> 4]);
302 GdbPutChar (mHexToStr[CheckSum & 0x0F]);
303
304 TestChar = GdbGetChar ();
305 } while (TestChar != '+');
306
307 return Count;
308 }
309
310 /**
311 Receive a GDB Remote Serial Protocol Packet
312
313 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
314 the packet terminating character '#' and the two digit checksum.
315
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.)
318
319 If an ack '+' is not sent resend the packet
320
321 @param PacketData Payload data for the packet
322
323 @retval Number of bytes of packet data received.
324
325 **/
326 UINTN
327 ReceivePacket (
328 OUT CHAR8 *PacketData,
329 IN UINTN PacketDataSize
330 )
331 {
332 UINT8 CheckSum;
333 UINTN Index;
334 CHAR8 Char;
335 CHAR8 SumString[3];
336 CHAR8 TestChar;
337
338 ZeroMem (PacketData, PacketDataSize);
339
340 for ( ; ;) {
341 // wait for the start of a packet
342 TestChar = GdbGetChar ();
343 while (TestChar != '$') {
344 TestChar = GdbGetChar ();
345 }
346
347 retry:
348 for (Index = 0, CheckSum = 0; Index < (PacketDataSize - 1); Index++) {
349 Char = GdbGetChar ();
350 if (Char == '$') {
351 goto retry;
352 }
353
354 if (Char == '#') {
355 break;
356 }
357
358 PacketData[Index] = Char;
359 CheckSum = CheckSum + Char;
360 }
361
362 PacketData[Index] = '\0';
363
364 if (Index == PacketDataSize) {
365 continue;
366 }
367
368 SumString[0] = GdbGetChar ();
369 SumString[1] = GdbGetChar ();
370 SumString[2] = '\0';
371
372 if (AsciiStrHexToUintn (SumString) == CheckSum) {
373 // Ack: Success
374 GdbPutChar ('+');
375
376 // Null terminate the callers string
377 PacketData[Index] = '\0';
378 return Index;
379 } else {
380 // Ack: Failure
381 GdbPutChar ('-');
382 }
383 }
384
385 // return 0;
386 }
387
388 /**
389 Empties the given buffer
390 @param Buf pointer to the first element in buffer to be emptied
391 **/
392 VOID
393 EmptyBuffer (
394 IN CHAR8 *Buf
395 )
396 {
397 *Buf = '\0';
398 }
399
400 /**
401 Converts an 8-bit Hex Char into a INTN.
402
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
406 **/
407 INTN
408 HexCharToInt (
409 IN CHAR8 Char
410 )
411 {
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')) {
417 return Char - '0';
418 } else {
419 // if not a hex value, return a negative value
420 return -1;
421 }
422 }
423
424 // 'E' + the biggest error number is 255, so its 2 hex digits + buffer end
425 CHAR8 *gError = "E__";
426
427 /** 'E NN'
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.
431
432 @param errno the error number that will be sent
433 **/
434 VOID
435 EFIAPI
436 SendError (
437 IN UINT8 ErrorNum
438 )
439 {
440 //
441 // Replace _, or old data, with current errno
442 //
443 gError[1] = mHexToStr[ErrorNum >> 4];
444 gError[2] = mHexToStr[ErrorNum & 0x0f];
445
446 SendPacket (gError); // send buffer
447 }
448
449 /**
450 Send 'OK' when the function is done executing successfully.
451 **/
452 VOID
453 EFIAPI
454 SendSuccess (
455 VOID
456 )
457 {
458 SendPacket ("OK"); // send buffer
459 }
460
461 /**
462 Send empty packet to specify that particular command/functionality is not supported.
463 **/
464 VOID
465 EFIAPI
466 SendNotSupported (
467 VOID
468 )
469 {
470 SendPacket ("");
471 }
472
473 /**
474 Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints
475
476 @param SystemContext Register content at time of the exception
477 @param GdbExceptionType GDB exception type
478 **/
479 VOID
480 GdbSendTSignal (
481 IN EFI_SYSTEM_CONTEXT SystemContext,
482 IN UINT8 GdbExceptionType
483 )
484 {
485 CHAR8 TSignalBuffer[128];
486 CHAR8 *TSignalPtr;
487 UINTN BreakpointDetected;
488 BREAK_TYPE BreakType;
489 UINTN DataAddress;
490 CHAR8 *WatchStrPtr = NULL;
491 UINTN RegSize;
492
493 TSignalPtr = &TSignalBuffer[0];
494
495 // Construct TSignal packet
496 *TSignalPtr++ = 'T';
497
498 //
499 // replace _, or previous value, with Exception type
500 //
501 *TSignalPtr++ = mHexToStr[GdbExceptionType >> 4];
502 *TSignalPtr++ = mHexToStr[GdbExceptionType & 0x0f];
503
504 if (GdbExceptionType == GDB_SIGTRAP) {
505 if (gSymbolTableUpdate) {
506 //
507 // We can only send back on reason code. So if the flag is set it means the breakpoint is from our event handler
508 //
509 WatchStrPtr = "library:;";
510 while (*WatchStrPtr != '\0') {
511 *TSignalPtr++ = *WatchStrPtr++;
512 }
513
514 gSymbolTableUpdate = FALSE;
515 } else {
516 //
517 // possible n:r pairs
518 //
519
520 // Retrieve the breakpoint number
521 BreakpointDetected = GetBreakpointDetected (SystemContext);
522
523 // Figure out if the exception is happend due to watch, rwatch or awatch.
524 BreakType = GetBreakpointType (SystemContext, BreakpointDetected);
525
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);
530
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";
538 }
539
540 while (*WatchStrPtr != '\0') {
541 *TSignalPtr++ = *WatchStrPtr++;
542 }
543
544 *TSignalPtr++ = ':';
545
546 // Set up series of bytes in big-endian byte order. "awatch" won't work with little-endian byte order.
547 RegSize = REG_SIZE;
548 while (RegSize > 0) {
549 RegSize = RegSize-4;
550 *TSignalPtr++ = mHexToStr[(UINT8)(DataAddress >> RegSize) & 0xf];
551 }
552
553 // Always end n:r pair with ';'
554 *TSignalPtr++ = ';';
555 }
556 }
557 }
558
559 *TSignalPtr = '\0';
560
561 SendPacket (TSignalBuffer);
562 }
563
564 /**
565 Translates the EFI mapping to GDB mapping
566
567 @param EFIExceptionType EFI Exception that is being processed
568 @retval UINTN that corresponds to EFIExceptionType's GDB exception type number
569 **/
570 UINT8
571 ConvertEFItoGDBtype (
572 IN EFI_EXCEPTION_TYPE EFIExceptionType
573 )
574 {
575 UINTN Index;
576
577 for (Index = 0; Index < MaxEfiException (); Index++) {
578 if (gExceptionType[Index].Exception == EFIExceptionType) {
579 return gExceptionType[Index].SignalNo;
580 }
581 }
582
583 return GDB_SIGTRAP; // this is a GDB trap
584 }
585
586 /** "m addr,length"
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
589 send it as a packet.
590 **/
591 VOID
592 EFIAPI
593 ReadFromMemory (
594 CHAR8 *PacketData
595 )
596 {
597 UINTN Address;
598 UINTN Length;
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
602
603 AddrBufPtr = AddressBuffer;
604 InBufPtr = &PacketData[1];
605 while (*InBufPtr != ',') {
606 *AddrBufPtr++ = *InBufPtr++;
607 }
608
609 *AddrBufPtr = '\0';
610
611 InBufPtr++; // this skips ',' in the buffer
612
613 /* Error checking */
614 if (AsciiStrLen (AddressBuffer) >= MAX_ADDR_SIZE) {
615 Print ((CHAR16 *)L"Address is too long\n");
616 SendError (GDB_EBADMEMADDRBUFSIZE);
617 return;
618 }
619
620 // 2 = 'm' + ','
621 if (AsciiStrLen (PacketData) - AsciiStrLen (AddressBuffer) - 2 >= MAX_LENGTH_SIZE) {
622 Print ((CHAR16 *)L"Length is too long\n");
623 SendError (GDB_EBADMEMLENGTH);
624 return;
625 }
626
627 Address = AsciiStrHexToUintn (AddressBuffer);
628 Length = AsciiStrHexToUintn (InBufPtr);
629
630 TransferFromMemToOutBufAndSend (Length, (unsigned char *)Address);
631 }
632
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
636 the input buffer.
637 **/
638 VOID
639 EFIAPI
640 WriteToMemory (
641 IN CHAR8 *PacketData
642 )
643 {
644 UINTN Address;
645 UINTN Length;
646 UINTN MessageLength;
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
652
653 AddrBufPtr = AddressBuffer;
654 LengthBufPtr = LengthBuffer;
655 InBufPtr = &PacketData[1];
656
657 while (*InBufPtr != ',') {
658 *AddrBufPtr++ = *InBufPtr++;
659 }
660
661 *AddrBufPtr = '\0';
662
663 InBufPtr++; // this skips ',' in the buffer
664
665 while (*InBufPtr != ':') {
666 *LengthBufPtr++ = *InBufPtr++;
667 }
668
669 *LengthBufPtr = '\0';
670
671 InBufPtr++; // this skips ':' in the buffer
672
673 Address = AsciiStrHexToUintn (AddressBuffer);
674 Length = AsciiStrHexToUintn (LengthBuffer);
675
676 /* Error checking */
677
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);
682 return;
683 }
684
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);
689 return;
690 }
691
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);
698 return;
699 }
700
701 TransferFromInBufToMem (Length, (unsigned char *)Address, InBufPtr);
702 }
703
704 /**
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
707 no error.
708
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)
713
714 @retval 1 Success
715 @retval {other} Particular error code
716
717 **/
718 UINTN
719 ParseBreakpointPacket (
720 IN CHAR8 *PacketData,
721 OUT UINTN *Type,
722 OUT UINTN *Address,
723 OUT UINTN *Length
724 )
725 {
726 CHAR8 AddressBuffer[MAX_ADDR_SIZE];
727 CHAR8 *AddressBufferPtr;
728 CHAR8 *PacketDataPtr;
729
730 PacketDataPtr = &PacketData[1];
731 AddressBufferPtr = AddressBuffer;
732
733 *Type = AsciiStrHexToUintn (PacketDataPtr);
734
735 // Breakpoint/watchpoint type should be between 0 to 4
736 if (*Type > 4) {
737 Print ((CHAR16 *)L"Type is invalid\n");
738 return 22; // EINVAL: Invalid argument.
739 }
740
741 // Skip ',' in the buffer.
742 while (*PacketDataPtr++ != ',') {
743 }
744
745 // Parse Address information
746 while (*PacketDataPtr != ',') {
747 *AddressBufferPtr++ = *PacketDataPtr++;
748 }
749
750 *AddressBufferPtr = '\0';
751
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.
756 }
757
758 *Address = AsciiStrHexToUintn (AddressBuffer);
759
760 PacketDataPtr++; // This skips , in the buffer
761
762 // Parse Length information
763 *Length = AsciiStrHexToUintn (PacketDataPtr);
764
765 // Length should be 1, 2 or 4 bytes
766 if (*Length > 4) {
767 Print ((CHAR16 *)L"Length is invalid\n");
768 return 22; // EINVAL: Invalid argument
769 }
770
771 return 0; // 0 = No error
772 }
773
774 UINTN
775 gXferObjectReadResponse (
776 IN CHAR8 Type,
777 IN CHAR8 *Str
778 )
779 {
780 CHAR8 *OutBufPtr; // pointer to the output buffer
781 CHAR8 Char;
782 UINTN Count;
783
784 // Response starts with 'm' or 'l' if it is the end
785 OutBufPtr = gOutBuffer;
786 *OutBufPtr++ = Type;
787 Count = 1;
788
789 // Binary data encoding
790 OutBufPtr = gOutBuffer;
791 while (*Str != '\0') {
792 Char = *Str++;
793 if ((Char == 0x7d) || (Char == 0x23) || (Char == 0x24) || (Char == 0x2a)) {
794 // escape character
795 *OutBufPtr++ = 0x7d;
796
797 Char ^= 0x20;
798 }
799
800 *OutBufPtr++ = Char;
801 Count++;
802 }
803
804 *OutBufPtr = '\0'; // the end of the buffer
805 SendPacket (gOutBuffer);
806
807 return Count;
808 }
809
810 /**
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.
814
815
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.
818
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().
826
827 @param Pe32Data Pointer to the PE/COFF image that is loaded in system
828 memory.
829 @param DebugBase Address that the debugger would use as the base of the image
830
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
833 valid.
834
835 **/
836 VOID *
837 EFIAPI
838 PeCoffLoaderGetDebuggerInfo (
839 IN VOID *Pe32Data,
840 OUT VOID **DebugBase
841 )
842 {
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;
847 UINTN DirCount;
848 VOID *CodeViewEntryPointer;
849 INTN TEImageAdjust;
850 UINT32 NumberOfRvaAndSizes;
851 UINT16 Magic;
852 UINTN SizeOfHeaders;
853
854 ASSERT (Pe32Data != NULL);
855
856 TEImageAdjust = 0;
857 DirectoryEntry = NULL;
858 DebugEntry = NULL;
859 NumberOfRvaAndSizes = 0;
860 SizeOfHeaders = 0;
861
862 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
863 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
864 //
865 // DOS image header is present, so read the PE header after the DOS image header.
866 //
867 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
868 } else {
869 //
870 // DOS image header is not present, so PE header is at the image base.
871 //
872 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
873 }
874
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 +
881 TEImageAdjust);
882 }
883
884 SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
885
886 // __APPLE__ check this math...
887 *DebugBase = ((CHAR8 *)Pe32Data) - TEImageAdjust;
888 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
889 *DebugBase = Pe32Data;
890
891 //
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.
895 //
896 switch (Hdr.Pe32->FileHeader.Machine) {
897 case EFI_IMAGE_MACHINE_IA32:
898 //
899 // Assume PE32 image with IA32 Machine field.
900 //
901 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
902 break;
903 case EFI_IMAGE_MACHINE_X64:
904 case EFI_IMAGE_MACHINE_IA64:
905 //
906 // Assume PE32+ image with X64 or IPF Machine field
907 //
908 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
909 break;
910 default:
911 //
912 // For unknown Machine field, use Magic in optional Header
913 //
914 Magic = Hdr.Pe32->OptionalHeader.Magic;
915 }
916
917 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
918 //
919 // Use PE32 offset get Debug Directory Entry
920 //
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) {
926 //
927 // Use PE32+ offset get Debug Directory Entry
928 //
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);
933 }
934
935 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
936 DirectoryEntry = NULL;
937 DebugEntry = NULL;
938 }
939 } else {
940 return NULL;
941 }
942
943 if ((DebugEntry == NULL) || (DirectoryEntry == NULL)) {
944 return NULL;
945 }
946
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));
959 default:
960 break;
961 }
962 }
963 }
964 }
965
966 (void)SizeOfHeaders;
967 return NULL;
968 }
969
970 /**
971 Process "qXfer:object:read:annex:offset,length" request.
972
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.
975
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:
979
980 <library-list>
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>
984 </library-list>
985
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.
992
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.
998
999 @param Offset offset into special data area
1000 @param Length number of bytes to read starting at Offset
1001
1002 **/
1003 VOID
1004 QxferLibrary (
1005 IN UINTN Offset,
1006 IN UINTN Length
1007 )
1008 {
1009 VOID *LoadAddress;
1010 CHAR8 *Pdb;
1011 UINTN Size;
1012
1013 if (Offset != gPacketqXferLibraryOffset) {
1014 SendError (GDB_EINVALIDARG);
1015 Print (L"\nqXferLibrary (%d, %d) != %d\n", Offset, Length, gPacketqXferLibraryOffset);
1016
1017 // Force a retry from the beginning
1018 gPacketqXferLibraryOffset = 0;
1019
1020 return;
1021 }
1022
1023 if (Offset == 0) {
1024 gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', "<library-list>\n");
1025
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;
1031 return;
1032 }
1033
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))
1039 {
1040 Pdb = PeCoffLoaderGetDebuggerInfo (
1041 gDebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase,
1042 &LoadAddress
1043 );
1044 if (Pdb != NULL) {
1045 Size = AsciiSPrint (
1046 gXferLibraryBuffer,
1047 sizeof (gXferLibraryBuffer),
1048 " <library name=\"%a\"><segment address=\"0x%p\"/></library>\n",
1049 Pdb,
1050 LoadAddress
1051 );
1052 if ((Size != 0) && (Size != (sizeof (gXferLibraryBuffer) - 1))) {
1053 gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', gXferLibraryBuffer);
1054
1055 // Update loop variables so we are in the right place when we get back
1056 gEfiDebugImageTableEntry++;
1057 gDebugTable++;
1058 return;
1059 } else {
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)
1065 //
1066 // But right now we just skip any entry that is too big
1067 }
1068 }
1069 }
1070 }
1071 }
1072 }
1073
1074 gXferObjectReadResponse ('l', "</library-list>\n");
1075 gPacketqXferLibraryOffset = 0;
1076 return;
1077 }
1078
1079 /**
1080 Exception Handler for GDB. It will be called for all exceptions
1081 registered via the gExceptionType[] array.
1082
1083 @param ExceptionType Exception that is being processed
1084 @param SystemContext Register content at time of the exception
1085 **/
1086 VOID
1087 EFIAPI
1088 GdbExceptionHandler (
1089 IN EFI_EXCEPTION_TYPE ExceptionType,
1090 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1091 )
1092 {
1093 UINT8 GdbExceptionType;
1094 CHAR8 *Ptr;
1095
1096 if (ValidateException (ExceptionType, SystemContext) == FALSE) {
1097 return;
1098 }
1099
1100 RemoveSingleStep (SystemContext);
1101
1102 GdbExceptionType = ConvertEFItoGDBtype (ExceptionType);
1103 GdbSendTSignal (SystemContext, GdbExceptionType);
1104
1105 for ( ; ; ) {
1106 ReceivePacket (gInBuffer, MAX_BUF_SIZE);
1107
1108 switch (gInBuffer[0]) {
1109 case '?':
1110 GdbSendTSignal (SystemContext, GdbExceptionType);
1111 break;
1112
1113 case 'c':
1114 ContinueAtAddress (SystemContext, gInBuffer);
1115 return;
1116
1117 case 'g':
1118 ReadGeneralRegisters (SystemContext);
1119 break;
1120
1121 case 'G':
1122 WriteGeneralRegisters (SystemContext, gInBuffer);
1123 break;
1124
1125 case 'H':
1126 // Return "OK" packet since we don't have more than one thread.
1127 SendSuccess ();
1128 break;
1129
1130 case 'm':
1131 ReadFromMemory (gInBuffer);
1132 break;
1133
1134 case 'M':
1135 WriteToMemory (gInBuffer);
1136 break;
1137
1138 case 'P':
1139 WriteNthRegister (SystemContext, gInBuffer);
1140 break;
1141
1142 //
1143 // Still debugging this code. Not used in Darwin
1144 //
1145 case 'q':
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++) {
1155 }
1156
1157 // Not sure if multi-radix support is required. Currently only support decimal
1158 QxferLibrary (AsciiStrHexToUintn (&gInBuffer[22]), AsciiStrHexToUintn (++Ptr));
1159 }
1160
1161 if (AsciiStrnCmp (gInBuffer, "qOffsets", 10) == 0) {
1162 AsciiSPrint (gOutBuffer, MAX_BUF_SIZE, "Text=1000;Data=f000;Bss=f000");
1163 SendPacket (gOutBuffer);
1164 } else {
1165 // Send empty packet
1166 SendNotSupported ();
1167 }
1168
1169 break;
1170
1171 case 's':
1172 SingleStep (SystemContext, gInBuffer);
1173 return;
1174
1175 case 'z':
1176 RemoveBreakPoint (SystemContext, gInBuffer);
1177 break;
1178
1179 case 'Z':
1180 InsertBreakPoint (SystemContext, gInBuffer);
1181 break;
1182
1183 default:
1184 // Send empty packet
1185 SendNotSupported ();
1186 break;
1187 }
1188 }
1189 }
1190
1191 /**
1192 Periodic callback for GDB. This function is used to catch a ctrl-c or other
1193 break in type command from GDB.
1194
1195 @param SystemContext Register content at time of the call
1196 **/
1197 VOID
1198 EFIAPI
1199 GdbPeriodicCallBack (
1200 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1201 )
1202 {
1203 //
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
1209 //
1210 if (!gCtrlCBreakFlag && !gProcessingFPacket) {
1211 //
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.
1214 //
1215 while (TRUE) {
1216 if (!GdbIsCharAvailable ()) {
1217 //
1218 // No characters are pending so exit the loop
1219 //
1220 break;
1221 }
1222
1223 if (GdbGetChar () == 0x03) {
1224 gCtrlCBreakFlag = TRUE;
1225 //
1226 // We have a ctrl-c so exit the loop
1227 //
1228 break;
1229 }
1230 }
1231 }
1232
1233 if (gCtrlCBreakFlag) {
1234 //
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.
1238 //
1239 AddSingleStep (SystemContext);
1240 gCtrlCBreakFlag = FALSE;
1241 }
1242 }