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