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