]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/GdbStub/GdbStub.c
Update the copyright notice format
[mirror_edk2.git] / EmbeddedPkg / GdbStub / GdbStub.c
CommitLineData
2ef2b01e
A
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.
9
10 All rights reserved. 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
14
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.
17
18**/
19
20#include <GdbStubInternal.h>
21#include <Protocol/DebugPort.h>
22
23
24UINTN gMaxProcessorIndex = 0;
25
26//
27// Buffers for basic gdb communication
28//
29CHAR8 gInBuffer[MAX_BUF_SIZE];
30CHAR8 gOutBuffer[MAX_BUF_SIZE];
31
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
34BOOLEAN gSymbolTableUpdate = FALSE;
35EFI_EVENT gEvent;
36VOID *gGdbSymbolEventHandlerRegistration = NULL;
37
38//
39// Globals for returning XML from qXfer:libraries:read packet
40//
41UINTN gPacketqXferLibraryOffset = 0;
42UINTN gEfiDebugImageTableEntry = 0;
43EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *gDebugImageTableHeader = NULL;
44EFI_DEBUG_IMAGE_INFO *gDebugTable = NULL;
45CHAR8 gXferLibraryBuffer[2000];
46
47GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexToStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
48
49
50VOID
51EFIAPI
52GdbSymbolEventHandler (
53 IN EFI_EVENT Event,
54 IN VOID *Context
55 )
56{
57}
58
59
60/**
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
63 function.
64
65 @param[in] ImageHandle The firmware allocated handle for the EFI image.
66 @param[in] SystemTable A pointer to the EFI System Table.
67
68 @retval EFI_SUCCESS The entry point is executed successfully.
69 @retval other Some error occurs when executing this entry point.
70
71**/
72EFI_STATUS
73EFIAPI
74GdbStubEntry (
75 IN EFI_HANDLE ImageHandle,
76 IN EFI_SYSTEM_TABLE *SystemTable
77 )
78
79{
80 EFI_STATUS Status;
81 EFI_DEBUG_SUPPORT_PROTOCOL *DebugSupport;
82 UINTN HandleCount;
83 EFI_HANDLE *Handles;
84 UINTN Index;
85 UINTN Processor;
86 BOOLEAN IsaSupported;
87
88
89 Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&gDebugImageTableHeader);
90 if (EFI_ERROR (Status)) {
91 gDebugImageTableHeader = NULL;
92 }
93
94 Status = gBS->LocateHandleBuffer (
95 ByProtocol,
96 &gEfiDebugSupportProtocolGuid,
97 NULL,
98 &HandleCount,
99 &Handles
100 );
101 if (EFI_ERROR (Status)) {
102 DEBUG ((EFI_D_ERROR, "Debug Support Protocol not found\n"));
103
104 return Status;
105 }
106
107 DebugSupport = NULL;
108 IsaSupported = FALSE;
109 do {
110 HandleCount--;
111 Status = gBS->HandleProtocol (
112 Handles[HandleCount],
113 &gEfiDebugSupportProtocolGuid,
114 (VOID **) &DebugSupport
115 );
116 if (!EFI_ERROR (Status)) {
117 if (CheckIsa (DebugSupport->Isa)) {
118 // We found what we are looking for so break out of the loop
119 IsaSupported = TRUE;
120 break;
121 }
122 }
123 } while (HandleCount > 0);
124 FreePool (Handles);
125
126 if (!IsaSupported) {
127 DEBUG ((EFI_D_ERROR, "Debug Support Protocol does not support our ISA\n"));
128
129 return EFI_NOT_FOUND;
130 }
131
132 Status = DebugSupport->GetMaximumProcessorIndex (DebugSupport, &gMaxProcessorIndex);
133 ASSERT_EFI_ERROR (Status);
134
135 // Make this an EFI_D_INFO after we get everything debugged.
136 DEBUG ((EFI_D_ERROR, "Debug Support Protocol ISA %x\n", DebugSupport->Isa));
137 DEBUG ((EFI_D_ERROR, "Debug Support Protocol Processor Index %d\n", gMaxProcessorIndex));
138
139 // Call processor-specific init routine
140 InitializeProcessor();
141
142 for (Processor = 0; Processor <= gMaxProcessorIndex; Processor++) {
143
144 for (Index = 0; Index < MaxEfiException (); Index++) {
145 Status = DebugSupport->RegisterExceptionCallback (DebugSupport, Processor, GdbExceptionHandler, gExceptionType[Index].Exception);
146 ASSERT_EFI_ERROR (Status);
147 }
148 //
149 // Current edk2 DebugPort is not interrupt context safe so we can not use it
150 //
151 Status = DebugSupport->RegisterPeriodicCallback (DebugSupport, Processor, GdbPeriodicCallBack);
152 ASSERT_EFI_ERROR (Status);
153 }
154
155 //
156 // This even fires every time an image is added. This allows the stub to know when gdb needs
157 // to update the symbol table.
158 //
159 Status = gBS->CreateEvent (
160 EVT_NOTIFY_SIGNAL,
161 TPL_CALLBACK,
162 GdbSymbolEventHandler,
163 NULL,
164 &gEvent
165 );
166 ASSERT_EFI_ERROR (Status);
167
168 //
169 // Register for protocol notifactions on this event
170 //
171 Status = gBS->RegisterProtocolNotify (
172 &gEfiLoadedImageProtocolGuid,
173 gEvent,
174 &gGdbSymbolEventHandlerRegistration
175 );
176 ASSERT_EFI_ERROR (Status);
177
178
179 if (PcdGetBool (PcdGdbSerial)) {
180 GdbInitializeSerialConsole ();
181 }
182
183 return EFI_SUCCESS;
184}
185
186
187
188/**
189 Transfer length bytes of input buffer, starting at Address, to memory.
190
191 @param length the number of the bytes to be transferred/written
192 @param *address the start address of the transferring/writing the memory
193 @param *new_data the new data to be written to memory
194 **/
195
196VOID
197TransferFromInBufToMem (
198 IN UINTN Length,
199 IN unsigned char *Address,
200 IN CHAR8 *NewData
201 )
202{
203 CHAR8 c1;
204 CHAR8 c2;
205
206 while (Length-- > 0) {
207 c1 = (CHAR8)HexCharToInt (*NewData++);
208 c2 = (CHAR8)HexCharToInt (*NewData++);
209
210 if ((c1 < 0) || (c2 < 0)) {
211 Print ((CHAR16 *)L"Bad message from write to memory..\n");
212 SendError (GDB_EBADMEMDATA);
213 return;
214 }
215 *Address++ = (UINT8)((c1 << 4) + c2);
216 }
217
218 SendSuccess();
219}
220
221
222/**
223 Transfer Length bytes of memory starting at Address to an output buffer, OutBuffer. This function will finally send the buffer
224 as a packet.
225
226 @param Length the number of the bytes to be transferred/read
227 @param *address pointer to the start address of the transferring/reading the memory
228 **/
229
230VOID
231TransferFromMemToOutBufAndSend (
232 IN UINTN Length,
233 IN unsigned char *Address
234 )
235{
236 // there are Length bytes and every byte is represented as 2 hex chars
237 CHAR8 OutBuffer[MAX_BUF_SIZE];
238 CHAR8 *OutBufPtr; // pointer to the output buffer
239 CHAR8 Char;
240
241 if (ValidateAddress(Address) == FALSE) {
242 SendError(14);
243 return;
244 }
245
246 OutBufPtr = OutBuffer;
247 while (Length > 0) {
248
249 Char = mHexToStr[*Address >> 4];
250 if ((Char >= 'A') && (Char <= 'F')) {
251 Char = Char - 'A' + 'a';
252 }
253 *OutBufPtr++ = Char;
254
255 Char = mHexToStr[*Address & 0x0f];
256 if ((Char >= 'A') && (Char <= 'F')) {
257 Char = Char - 'A' + 'a';
258 }
259 *OutBufPtr++ = Char;
260
261 Address++;
262 Length--;
263 }
264
265 *OutBufPtr = '\0' ; // the end of the buffer
266 SendPacket (OutBuffer);
267}
268
269
270
271/**
272 Send a GDB Remote Serial Protocol Packet
273
274 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
275 the packet teminating character '#' and the two digit checksum.
276
277 If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up
278 in an infinit loop. This is so if you unplug the debugger code just keeps running
279
280 @param PacketData Payload data for the packet
281
282
283 @retval Number of bytes of packet data sent.
284
285**/
286UINTN
287SendPacket (
288 IN CHAR8 *PacketData
289 )
290{
291 UINT8 CheckSum;
292 UINTN Timeout;
293 CHAR8 *Ptr;
294 CHAR8 TestChar;
295 UINTN Count;
296
297 Timeout = PcdGet32 (PcdGdbMaxPacketRetryCount);
298
299 Count = 0;
300 do {
301
302 Ptr = PacketData;
303
304 if (Timeout-- == 0) {
305 // Only try a finite number of times so we don't get stuck in the loop
306 return Count;
307 }
308
309 // Packet prefix
310 GdbPutChar ('$');
311
312 for (CheckSum = 0, Count =0 ; *Ptr != '\0'; Ptr++, Count++) {
313 GdbPutChar (*Ptr);
314 CheckSum = CheckSum + *Ptr;
315 }
316
317 // Packet terminating character and checksum
318 GdbPutChar ('#');
319 GdbPutChar (mHexToStr[CheckSum >> 4]);
320 GdbPutChar (mHexToStr[CheckSum & 0x0F]);
321
322 TestChar = GdbGetChar ();
323 } while (TestChar != '+');
324
325 return Count;
326}
327
328/**
329 Receive a GDB Remote Serial Protocol Packet
330
331 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
332 the packet teminating character '#' and the two digit checksum.
333
334 If host re-starts sending a packet without ending the previous packet, only the last valid packet is proccessed.
335 (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)
336
337 If an ack '+' is not sent resend the packet
338
339 @param PacketData Payload data for the packet
340
341 @retval Number of bytes of packet data received.
342
343**/
344UINTN
345ReceivePacket (
346 OUT CHAR8 *PacketData,
347 IN UINTN PacketDataSize
348 )
349{
350 UINT8 CheckSum;
351 UINTN Index;
352 CHAR8 Char;
353 CHAR8 SumString[3];
354 CHAR8 TestChar;
355
356 ZeroMem (PacketData, PacketDataSize);
357
358 for (;;) {
359 // wait for the start of a packet
360 TestChar = GdbGetChar ();
361 while (TestChar != '$') {
362 TestChar = GdbGetChar ();
363 };
364
365 retry:
366 for (Index = 0, CheckSum = 0; Index < (PacketDataSize - 1); Index++) {
367 Char = GdbGetChar ();
368 if (Char == '$') {
369 goto retry;
370 }
371 if (Char == '#') {
372 break;
373 }
374
375 PacketData[Index] = Char;
376 CheckSum = CheckSum + Char;
377 }
378 PacketData[Index] = '\0';
379
380 if (Index == PacketDataSize) {
381 continue;
382 }
383
384 SumString[0] = GdbGetChar ();
385 SumString[1] = GdbGetChar ();
386 SumString[2] = '\0';
387
388 if (AsciiStrHexToUintn (SumString) == CheckSum) {
389 // Ack: Success
390 GdbPutChar ('+');
391
392 // Null terminate the callers string
393 PacketData[Index] = '\0';
394 return Index;
395 } else {
396 // Ack: Failure
397 GdbPutChar ('-');
398 }
399 }
400
401 //return 0;
402}
403
404
405/**
406 Empties the given buffer
407 @param Buf pointer to the first element in buffer to be emptied
408 **/
409VOID
410EmptyBuffer (
411 IN CHAR8 *Buf
412 )
413{
414 *Buf = '\0';
415}
416
417
418/**
419 Converts an 8-bit Hex Char into a INTN.
420
421 @param Char the hex character to be converted into UINTN
422 @retval a INTN, from 0 to 15, that corressponds to Char
423 -1 if Char is not a hex character
424 **/
425INTN
426HexCharToInt (
427 IN CHAR8 Char
428 )
429{
430 if ((Char >= 'A') && (Char <= 'F')) {
431 return Char - 'A' + 10;
432 } else if ((Char >= 'a') && (Char <= 'f')) {
433 return Char - 'a' + 10;
434 } else if ((Char >= '0') && (Char <= '9')) {
435 return Char - '0';
436 } else { // if not a hex value, return a negative value
437 return -1;
438 }
439}
440
441 // 'E' + the biggest error number is 255, so its 2 hex digits + buffer end
442CHAR8 *gError = "E__";
443
444/** 'E NN'
445 Send an error with the given error number after converting to hex.
446 The error number is put into the buffer in hex. '255' is the biggest errno we can send.
447 ex: 162 will be sent as A2.
448
449 @param errno the error number that will be sent
450 **/
451VOID
452EFIAPI
453SendError (
454 IN UINT8 ErrorNum
455 )
456{
457 //
458 // Replace _, or old data, with current errno
459 //
460 gError[1] = mHexToStr [ErrorNum >> 4];
461 gError[2] = mHexToStr [ErrorNum & 0x0f];
462
463 SendPacket (gError); // send buffer
464}
465
466
467
468/**
469 Send 'OK' when the function is done executing successfully.
470 **/
471VOID
472EFIAPI
473SendSuccess (
474 VOID
475 )
476{
477 SendPacket ("OK"); // send buffer
478}
479
480
481/**
482 Send empty packet to specify that particular command/functionality is not supported.
483 **/
484VOID
485EFIAPI
486SendNotSupported (
487 VOID
488 )
489{
490 SendPacket ("");
491}
492
493
494
495/**
496 Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints
497
498 @param SystemContext Register content at time of the exception
499 @param GdbExceptionType GDB exception type
500 **/
501VOID
502GdbSendTSignal (
503 IN EFI_SYSTEM_CONTEXT SystemContext,
504 IN UINT8 GdbExceptionType
505 )
506{
507 CHAR8 TSignalBuffer[128];
508 CHAR8 *TSignalPtr;
509 UINTN BreakpointDetected;
510 BREAK_TYPE BreakType;
511 UINTN DataAddress;
512 CHAR8 *WatchStrPtr = NULL;
513 UINTN RegSize;
514
515 TSignalPtr = &TSignalBuffer[0];
516
517 //Construct TSignal packet
518 *TSignalPtr++ = 'T';
519
520 //
521 // replace _, or previous value, with Exception type
522 //
523 *TSignalPtr++ = mHexToStr [GdbExceptionType >> 4];
524 *TSignalPtr++ = mHexToStr [GdbExceptionType & 0x0f];
525
526 if (GdbExceptionType == GDB_SIGTRAP) {
527 if (gSymbolTableUpdate) {
528 //
529 // We can only send back on reason code. So if the flag is set it means the breakpoint is from our event handler
530 //
531 WatchStrPtr = "library:;";
532 while (*WatchStrPtr != '\0') {
533 *TSignalPtr++ = *WatchStrPtr++;
534 }
535 gSymbolTableUpdate = FALSE;
536 } else {
537
538
539 //
540 // possible n:r pairs
541 //
542
543 //Retrieve the breakpoint number
544 BreakpointDetected = GetBreakpointDetected (SystemContext);
545
546 //Figure out if the exception is happend due to watch, rwatch or awatch.
547 BreakType = GetBreakpointType (SystemContext, BreakpointDetected);
548
549 //INFO: rwatch is not supported due to the way IA32 debug registers work
550 if ((BreakType == DataWrite) || (BreakType == DataRead) || (BreakType == DataReadWrite)) {
551
552 //Construct n:r pair
553 DataAddress = GetBreakpointDataAddress (SystemContext, BreakpointDetected);
554
555 //Assign appropriate buffer to print particular watchpoint type
556 if (BreakType == DataWrite) {
557 WatchStrPtr = "watch";
558 } else if (BreakType == DataRead) {
559 WatchStrPtr = "rwatch";
560 } else if (BreakType == DataReadWrite) {
561 WatchStrPtr = "awatch";
562 }
563
564 while (*WatchStrPtr != '\0') {
565 *TSignalPtr++ = *WatchStrPtr++;
566 }
567
568 *TSignalPtr++ = ':';
569
570 //Set up series of bytes in big-endian byte order. "awatch" won't work with little-endian byte order.
571 RegSize = REG_SIZE;
572 while (RegSize > 0) {
573 RegSize = RegSize-4;
574 *TSignalPtr++ = mHexToStr[(UINT8)(DataAddress >> RegSize) & 0xf];
575 }
576
577 //Always end n:r pair with ';'
578 *TSignalPtr++ = ';';
579 }
580 }
581 }
582
583 *TSignalPtr = '\0';
584
585 SendPacket (TSignalBuffer);
586}
587
588
589/**
590 Translates the EFI mapping to GDB mapping
591
592 @param EFIExceptionType EFI Exception that is being processed
593 @retval UINTN that corresponds to EFIExceptionType's GDB exception type number
594 **/
595UINT8
596ConvertEFItoGDBtype (
597 IN EFI_EXCEPTION_TYPE EFIExceptionType
598 )
599{
600 UINTN i;
601
602 for (i=0; i < MaxEfiException() ; i++) {
603 if (gExceptionType[i].Exception == EFIExceptionType) {
604 return gExceptionType[i].SignalNo;
605 }
606 }
607 return GDB_SIGTRAP; // this is a GDB trap
608}
609
610
611/** "m addr,length"
612 Find the Length of the area to read and the start addres. Finally, pass them to
613 another function, TransferFromMemToOutBufAndSend, that will read from that memory space and
614 send it as a packet.
615 **/
616
617VOID
618EFIAPI
619ReadFromMemory (
620 CHAR8 *PacketData
621 )
622{
623 UINTN Address;
624 UINTN Length;
625 CHAR8 AddressBuffer[MAX_ADDR_SIZE]; // the buffer that will hold the address in hex chars
626 CHAR8 *AddrBufPtr; // pointer to the address buffer
627 CHAR8 *InBufPtr; /// pointer to the input buffer
628
629 AddrBufPtr = AddressBuffer;
630 InBufPtr = &PacketData[1];
631 while (*InBufPtr != ',') {
632 *AddrBufPtr++ = *InBufPtr++;
633 }
634 *AddrBufPtr = '\0';
635
636 InBufPtr++; // this skips ',' in the buffer
637
638 /* Error checking */
639 if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) {
640 Print((CHAR16 *)L"Address is too long\n");
641 SendError (GDB_EBADMEMADDRBUFSIZE);
642 return;
643 }
644
645 // 2 = 'm' + ','
646 if (AsciiStrLen(PacketData) - AsciiStrLen(AddressBuffer) - 2 >= MAX_LENGTH_SIZE) {
647 Print((CHAR16 *)L"Length is too long\n");
648 SendError (GDB_EBADMEMLENGTH);
649 return;
650 }
651
652 Address = AsciiStrHexToUintn (AddressBuffer);
653 Length = AsciiStrHexToUintn (InBufPtr);
654
655 TransferFromMemToOutBufAndSend (Length, (unsigned char *)Address);
656}
657
658
659/** "M addr,length :XX..."
660 Find the Length of the area in bytes to write and the start addres. Finally, pass them to
661 another function, TransferFromInBufToMem, that will write to that memory space the info in
662 the input buffer.
663 **/
664VOID
665EFIAPI
666WriteToMemory (
667 IN CHAR8 *PacketData
668 )
669{
670 UINTN Address;
671 UINTN Length;
672 UINTN MessageLength;
673 CHAR8 AddressBuffer[MAX_ADDR_SIZE]; // the buffer that will hold the Address in hex chars
674 CHAR8 LengthBuffer[MAX_LENGTH_SIZE]; // the buffer that will hold the Length in hex chars
675 CHAR8 *AddrBufPtr; // pointer to the Address buffer
676 CHAR8 *LengthBufPtr; // pointer to the Length buffer
677 CHAR8 *InBufPtr; /// pointer to the input buffer
678
679 AddrBufPtr = AddressBuffer;
680 LengthBufPtr = LengthBuffer;
681 InBufPtr = &PacketData[1];
682
683 while (*InBufPtr != ',') {
684 *AddrBufPtr++ = *InBufPtr++;
685 }
686 *AddrBufPtr = '\0';
687
688 InBufPtr++; // this skips ',' in the buffer
689
690 while (*InBufPtr != ':') {
691 *LengthBufPtr++ = *InBufPtr++;
692 }
693 *LengthBufPtr = '\0';
694
695 InBufPtr++; // this skips ':' in the buffer
696
697 Address = AsciiStrHexToUintn (AddressBuffer);
698 Length = AsciiStrHexToUintn (LengthBuffer);
699
700 /* Error checking */
701
702 //Check if Address is not too long.
703 if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) {
704 Print ((CHAR16 *)L"Address too long..\n");
705 SendError (GDB_EBADMEMADDRBUFSIZE);
706 return;
707 }
708
709 //Check if message length is not too long
710 if (AsciiStrLen(LengthBuffer) >= MAX_LENGTH_SIZE) {
711 Print ((CHAR16 *)L"Length too long..\n");
712 SendError (GDB_EBADMEMLENGBUFSIZE);
713 return;
714 }
715
716 // Check if Message is not too long/short.
717 // 3 = 'M' + ',' + ':'
718 MessageLength = (AsciiStrLen(PacketData) - AsciiStrLen(AddressBuffer) - AsciiStrLen(LengthBuffer) - 3);
719 if (MessageLength != (2*Length)) {
720 //Message too long/short. New data is not the right size.
721 SendError (GDB_EBADMEMDATASIZE);
722 return;
723 }
724 TransferFromInBufToMem (Length, (unsigned char *)Address, InBufPtr);
725}
726
727/**
728 Parses breakpoint packet data and captures Breakpoint type, Address and length.
729 In case of an error, function returns particular error code. Returning 0 meaning
730 no error.
731
732 @param PacketData Pointer to the payload data for the packet.
733 @param Type Breakpoint type
734 @param Address Breakpoint address
735 @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
736
737 @retval 1 Success
738 @retval {other} Particular error code
739
740**/
741UINTN
742ParseBreakpointPacket (
743 IN CHAR8 *PacketData,
744 OUT UINTN *Type,
745 OUT UINTN *Address,
746 OUT UINTN *Length
747 )
748{
749 CHAR8 AddressBuffer[MAX_ADDR_SIZE];
750 CHAR8 *AddressBufferPtr;
751 CHAR8 *PacketDataPtr;
752
753 PacketDataPtr = &PacketData[1];
754 AddressBufferPtr = AddressBuffer;
755
756 *Type = AsciiStrHexToUintn (PacketDataPtr);
757
758 //Breakpoint/watchpoint type should be between 0 to 4
759 if (*Type > 4) {
760 Print ((CHAR16 *)L"Type is invalid\n");
761 return 22; //EINVAL: Invalid argument.
762 }
763
764 //Skip ',' in the buffer.
765 while (*PacketDataPtr++ != ',');
766
767 //Parse Address information
768 while (*PacketDataPtr != ',') {
769 *AddressBufferPtr++ = *PacketDataPtr++;
770 }
771 *AddressBufferPtr = '\0';
772
773 //Check if Address is not too long.
774 if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) {
775 Print ((CHAR16 *)L"Address too long..\n");
776 return 40; //EMSGSIZE: Message size too long.
777 }
778
779 *Address = AsciiStrHexToUintn (AddressBuffer);
780
781 PacketDataPtr++; //This skips , in the buffer
782
783 //Parse Length information
784 *Length = AsciiStrHexToUintn (PacketDataPtr);
785
786 //Length should be 1, 2 or 4 bytes
787 if (*Length > 4) {
788 Print ((CHAR16 *)L"Length is invalid\n");
789 return 22; //EINVAL: Invalid argument
790 }
791
792 return 0; //0 = No error
793}
794
795UINTN
796gXferObjectReadResponse (
797 IN CHAR8 Type,
798 IN CHAR8 *Str
799 )
800{
801 CHAR8 *OutBufPtr; // pointer to the output buffer
802 CHAR8 Char;
803 UINTN Count;
804
805 // responce starts with 'm' or 'l' if it is the end
806 OutBufPtr = gOutBuffer;
807 *OutBufPtr++ = Type;
808 Count = 1;
809
810 // Binary data encoding
811 OutBufPtr = gOutBuffer;
812 while (*Str != '\0') {
813 Char = *Str++;
814 if ((Char == 0x7d) || (Char == 0x23) || (Char == 0x24) || (Char == 0x2a)) {
815 // escape character
816 *OutBufPtr++ = 0x7d;
817
818 Char ^= 0x20;
819 }
820 *OutBufPtr++ = Char;
821 Count++;
822 }
823
824 *OutBufPtr = '\0' ; // the end of the buffer
825 SendPacket (gOutBuffer);
826
827 return Count;
828}
829
830
831/**
832 Note: This should be a library function. In the Apple case you have to add
833 the size of the PE/COFF header into the starting address to make things work
834 right as there is no way to pad the Mach-O for the size of the PE/COFF header.
835
836
837 Returns a pointer to the PDB file name for a PE/COFF image that has been
838 loaded into system memory with the PE/COFF Loader Library functions.
839
840 Returns the PDB file name for the PE/COFF image specified by Pe32Data. If
841 the PE/COFF image specified by Pe32Data is not a valid, then NULL is
842 returned. If the PE/COFF image specified by Pe32Data does not contain a
843 debug directory entry, then NULL is returned. If the debug directory entry
844 in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
845 then NULL is returned.
846 If Pe32Data is NULL, then ASSERT().
847
848 @param Pe32Data Pointer to the PE/COFF image that is loaded in system
849 memory.
850 @param DebugBase Address that the debugger would use as the base of the image
851
852 @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
853 if it cannot be retrieved. DebugBase is only valid if PDB file name is
854 valid.
855
856**/
857VOID *
858EFIAPI
859PeCoffLoaderGetDebuggerInfo (
860 IN VOID *Pe32Data,
861 OUT VOID **DebugBase
862 )
863{
864 EFI_IMAGE_DOS_HEADER *DosHdr;
865 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
866 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
867 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
868 UINTN DirCount;
869 VOID *CodeViewEntryPointer;
870 INTN TEImageAdjust;
871 UINT32 NumberOfRvaAndSizes;
872 UINT16 Magic;
873 UINTN SizeOfHeaders;
874
875 ASSERT (Pe32Data != NULL);
876
877 TEImageAdjust = 0;
878 DirectoryEntry = NULL;
879 DebugEntry = NULL;
880 NumberOfRvaAndSizes = 0;
881 SizeOfHeaders = 0;
882
883 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
884 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
885 //
886 // DOS image header is present, so read the PE header after the DOS image header.
887 //
888 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
889 } else {
890 //
891 // DOS image header is not present, so PE header is at the image base.
892 //
893 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
894 }
895
896 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
897 if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
898 DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
899 TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
900 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +
901 Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +
902 TEImageAdjust);
903 }
904 SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
905
906 // __APPLE__ check this math...
907 *DebugBase = ((CHAR8 *)Pe32Data) - TEImageAdjust;
908 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
909
910 *DebugBase = Pe32Data;
911
912
913 //
914 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
915 // It is due to backward-compatibility, for some system might
916 // generate PE32+ image with PE32 Magic.
917 //
918 switch (Hdr.Pe32->FileHeader.Machine) {
919 case EFI_IMAGE_MACHINE_IA32:
920 //
921 // Assume PE32 image with IA32 Machine field.
922 //
923 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
924 break;
925 case EFI_IMAGE_MACHINE_X64:
926 case EFI_IMAGE_MACHINE_IA64:
927 //
928 // Assume PE32+ image with X64 or IPF Machine field
929 //
930 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
931 break;
932 default:
933 //
934 // For unknow Machine field, use Magic in optional Header
935 //
936 Magic = Hdr.Pe32->OptionalHeader.Magic;
937 }
938
939 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
940 //
941 // Use PE32 offset get Debug Directory Entry
942 //
943 SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
944 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
945 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
946 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
947 } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
948 //
949 // Use PE32+ offset get Debug Directory Entry
950 //
951 SizeOfHeaders = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
952 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
953 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
954 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
955 }
956
957 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
958 DirectoryEntry = NULL;
959 DebugEntry = NULL;
960 }
961 } else {
962 return NULL;
963 }
964
965 if (DebugEntry == NULL || DirectoryEntry == NULL) {
966 return NULL;
967 }
968
969 for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {
970 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
971 if (DebugEntry->SizeOfData > 0) {
972 CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);
973 switch (* (UINT32 *) CodeViewEntryPointer) {
974 case CODEVIEW_SIGNATURE_NB10:
975 return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));
976 case CODEVIEW_SIGNATURE_RSDS:
977 return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));
978 case CODEVIEW_SIGNATURE_MTOC:
920cb926 979 *DebugBase = (VOID *)(UINTN)((UINTN)DebugBase - SizeOfHeaders);
2ef2b01e
A
980 return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY));
981 default:
982 break;
983 }
984 }
985 }
986 }
987
988 (void)SizeOfHeaders;
989 return NULL;
990}
991
992
993
994/**
995 Process "qXfer:object:read:annex:offset,length" request.
996
997 Returns an XML document that contains loaded libraries. In our case it is
998 infomration in the EFI Debug Inmage Table converted into an XML document.
999
1000 GDB will call with an arbitrary length (it can't know the real length and
1001 will reply with chunks of XML that are easy for us to deal with. Gdb will
1002 keep calling until we say we are done. XML doc looks like:
1003
1004 <library-list>
1005 <library name="/a/a/c/d.dSYM"><segment address="0x10000000"/></library>
1006 <library name="/a/m/e/e.pdb"><segment address="0x20000000"/></library>
1007 <library name="/a/l/f/f.dll"><segment address="0x30000000"/></library>
1008 </library-list>
1009
1010 Since we can not allocate memory in interupt context this module has
1011 assumptions about how it will get called:
1012 1) Length will generally be max remote packet size (big enough)
1013 2) First Offset of an XML document read needs to be 0
1014 3) This code will return back small chunks of the XML document on every read.
1015 Each subseqent call will ask for the next availble part of the document.
1016
1017 Note: The only variable size element in the XML is:
1018 " <library name=\"%s\"><segment address=\"%p\"/></library>\n" and it is
1019 based on the file path and name of the symbol file. If the symbol file name
1020 is bigger than the max gdb remote packet size we could update this code
1021 to respond back in chunks.
1022
1023 @param Offset offset into special data area
1024 @param Length number of bytes to read starting at Offset
1025
1026 **/
1027VOID
1028QxferLibrary (
1029 IN UINTN Offset,
1030 IN UINTN Length
1031 )
1032{
1033 VOID *LoadAddress;
1034 CHAR8 *Pdb;
1035 UINTN Size;
1036
1037 if (Offset != gPacketqXferLibraryOffset) {
1038 SendError (GDB_EINVALIDARG);
1039 Print (L"\nqXferLibrary (%d, %d) != %d\n", Offset, Length, gPacketqXferLibraryOffset);
1040
1041 // Force a retry from the beginning
1042 gPacketqXferLibraryOffset = 0;
1043 return;
1044 }
1045
1046 if (Offset == 0) {
1047 gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', "<library-list>\n");
1048
1049 // The owner of the table may have had to ralloc it so grab a fresh copy every time
1050 // we assume qXferLibrary will get called over and over again until the entire XML table is
1051 // returned in a tight loop. Since we are in the debugger the table should not get updated
1052 gDebugTable = gDebugImageTableHeader->EfiDebugImageInfoTable;
1053 gEfiDebugImageTableEntry = 0;
1054 return;
1055 }
1056
1057 if (gDebugTable != NULL) {
1058 for (; gEfiDebugImageTableEntry < gDebugImageTableHeader->TableSize; gEfiDebugImageTableEntry++, gDebugTable++) {
1059 if (gDebugTable->NormalImage != NULL) {
1060 if ((gDebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) &&
1061 (gDebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {
1062 Pdb = PeCoffLoaderGetDebuggerInfo (
1063 gDebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase,
1064 &LoadAddress
1065 );
1066 if (Pdb != NULL) {
1067 Size = AsciiSPrint (
1068 gXferLibraryBuffer,
1069 sizeof (gXferLibraryBuffer),
1070 " <library name=\"%a\"><segment address=\"0x%p\"/></library>\n",
1071 Pdb,
1072 LoadAddress
1073 );
1074 if ((Size != 0) && (Size != (sizeof (gXferLibraryBuffer) - 1))) {
1075 gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', gXferLibraryBuffer);
1076
1077 // Update loop variables so we are in the right place when we get back
1078 gEfiDebugImageTableEntry++;
1079 gDebugTable++;
1080 return;
1081 } else {
1082 // We could handle <library> entires larger than sizeof (gXferLibraryBuffer) here if
1083 // needed by breaking up into N packets
1084 // "<library name=\"%s
1085 // the rest of the string (as many packets as required
1086 // \"><segment address=\"%d\"/></library> (fixed size)
1087 //
1088 // But right now we just skip any entry that is too big
1089 }
1090 }
1091 }
1092 }
1093 }
1094 }
1095
1096
1097 gXferObjectReadResponse ('l', "</library-list>\n");
1098 gPacketqXferLibraryOffset = 0;
1099 return;
1100}
1101
1102
1103/**
1104 Exception Hanldler for GDB. It will be called for all exceptions
1105 registered via the gExceptionType[] array.
1106
1107 @param ExceptionType Exception that is being processed
1108 @param SystemContext Register content at time of the exception
1109 **/
1110VOID
1111EFIAPI
1112GdbExceptionHandler (
1113 IN EFI_EXCEPTION_TYPE ExceptionType,
1114 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1115 )
1116{
1117 UINT8 GdbExceptionType;
1118 CHAR8 *Ptr;
1119
1120
1121 if (ValidateException(ExceptionType, SystemContext) == FALSE) {
1122 return;
1123 }
1124
1125 RemoveSingleStep (SystemContext);
1126
1127 GdbExceptionType = ConvertEFItoGDBtype (ExceptionType);
1128 GdbSendTSignal (SystemContext, GdbExceptionType);
1129
1130 for( ; ; ) {
1131 ReceivePacket (gInBuffer, MAX_BUF_SIZE);
1132
1133 switch (gInBuffer[0]) {
1134 case '?':
1135 GdbSendTSignal (SystemContext, GdbExceptionType);
1136 break;
1137
1138 case 'c':
1139 ContinueAtAddress (SystemContext, gInBuffer);
1140 return;
1141
1142 case 'g':
1143 ReadGeneralRegisters (SystemContext);
1144 break;
1145
1146 case 'G':
1147 WriteGeneralRegisters (SystemContext, gInBuffer);
1148 break;
1149
1150 case 'H':
1151 //Return "OK" packet since we don't have more than one thread.
1152 SendSuccess ();
1153 break;
1154
1155 case 'm':
1156 ReadFromMemory (gInBuffer);
1157 break;
1158
1159 case 'M':
1160 WriteToMemory (gInBuffer);
1161 break;
1162
1163 case 'P':
1164 WriteNthRegister (SystemContext, gInBuffer);
1165 break;
1166
1167 //
1168 // Still debugging this code. Not used in Darwin
1169 //
1170 case 'q':
1171 // General Query Packets
1172 if (AsciiStrnCmp (gInBuffer, "qSupported", 10) == 0) {
1173 // return what we currently support, we don't parse what gdb suports
1174 AsciiSPrint (gOutBuffer, MAX_BUF_SIZE, "qXfer:libraries:read+;PacketSize=%d", MAX_BUF_SIZE);
1175 SendPacket (gOutBuffer);
1176 } else if (AsciiStrnCmp (gInBuffer, "qXfer:libraries:read::", 22) == 0) {
1177 // ‘qXfer:libraries:read::offset,length
1178 // gInBuffer[22] is offset string, ++Ptr is length string’
1179 for (Ptr = &gInBuffer[22]; *Ptr != ','; Ptr++);
1180
1181 // Not sure if multi-radix support is required. Currently only support decimal
1182 QxferLibrary (AsciiStrHexToUintn (&gInBuffer[22]), AsciiStrHexToUintn (++Ptr));
1183 } if (AsciiStrnCmp (gInBuffer, "qOffsets", 10) == 0) {
1184 AsciiSPrint (gOutBuffer, MAX_BUF_SIZE, "Text=1000;Data=f000;Bss=f000");
1185 SendPacket (gOutBuffer);
1186 } else {
1187 //Send empty packet
1188 SendNotSupported ();
1189 }
1190 break;
1191
1192 case 's':
1193 SingleStep (SystemContext, gInBuffer);
1194 return;
1195
1196 case 'z':
1197 RemoveBreakPoint (SystemContext, gInBuffer);
1198 break;
1199
1200 case 'Z':
1201 InsertBreakPoint (SystemContext, gInBuffer);
1202 break;
1203
1204 default:
1205 //Send empty packet
1206 SendNotSupported ();
1207 break;
1208 }
1209 }
1210}
1211
1212
1213/**
1214 Periodic callback for GDB. This function is used to catch a ctrl-c or other
1215 break in type command from GDB.
1216
1217 @param SystemContext Register content at time of the call
1218 **/
1219VOID
1220EFIAPI
1221GdbPeriodicCallBack (
1222 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1223 )
1224{
1225 //
1226 // gCtrlCBreakFlag may have been set from a previous F response package
1227 // and we set the global as we need to process it at a point where we
1228 // can update the system context. If we are in the middle of processing
1229 // a F Packet it is not safe to read the GDB serial stream so we need
1230 // to skip it on this check
1231 //
1232 if (!gCtrlCBreakFlag && !gProcessingFPacket) {
1233 //
1234 // Ctrl-C was not pending so grab any pending characters and see if they
1235 // are a Ctrl-c (0x03). If so set the Ctrl-C global.
1236 //
1237 while (TRUE) {
1238 if (!GdbIsCharAvailable ()) {
1239 //
1240 // No characters are pending so exit the loop
1241 //
1242 break;
1243 }
1244
1245 if (GdbGetChar () == 0x03) {
1246 gCtrlCBreakFlag = TRUE;
1247 //
1248 // We have a ctrl-c so exit the loop
1249 //
1250 break;
1251 }
1252 }
1253 }
1254
1255 if (gCtrlCBreakFlag) {
1256 //
1257 // Update the context to force a single step trap when we exit the GDB
1258 // stub. This will trasfer control to GdbExceptionHandler () and let
1259 // us break into the program. We don't want to break into the GDB stub.
1260 //
1261 AddSingleStep (SystemContext);
1262 gCtrlCBreakFlag = FALSE;
1263 }
1264}