2 Debug Agent library implementition with empty functions.
4 Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "GdbDebugAgent.h"
18 UINTN gMaxProcessorIndex
= 0;
21 // Buffers for basic gdb communication
23 CHAR8 gInBuffer
[MAX_BUF_SIZE
];
24 CHAR8 gOutBuffer
[MAX_BUF_SIZE
];
28 // Globals for returning XML from qXfer:libraries:read packet
30 UINTN gPacketqXferLibraryOffset
= 0;
31 UINTN gEfiDebugImageTableEntry
= 0;
32 CHAR8 gXferLibraryBuffer
[2000];
34 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexToStr
[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
37 // add-symbol-file c:/work/edk2/Build/BeagleBoard/DEBUG_GCC48/ARM/BeagleBoardPkg/Sec/Sec/DEBUG/BeagleBoardSec.dll 0x80008360
38 CHAR8
*qXferHack
= "<library name=\"c:/work/edk2/Build/BeagleBoard/DEBUG_GCC48/ARM/BeagleBoardPkg/Sec/Sec/DEBUG/BeagleBoardSec.dll\"><segment address=\"0x80008360\"/></library>";
41 gXferObjectReadResponse (
46 CHAR8
*OutBufPtr
; // pointer to the output buffer
50 // responce starts with 'm' or 'l' if it is the end
51 OutBufPtr
= gOutBuffer
;
55 // Binary data encoding
56 OutBufPtr
= gOutBuffer
;
57 while (*Str
!= '\0') {
59 if ((Char
== 0x7d) || (Char
== 0x23) || (Char
== 0x24) || (Char
== 0x2a)) {
69 *OutBufPtr
= '\0' ; // the end of the buffer
70 SendPacket (gOutBuffer
);
76 Process "qXfer:object:read:annex:offset,length" request.
78 Returns an XML document that contains loaded libraries. In our case it is
79 infomration in the EFI Debug Inmage Table converted into an XML document.
81 GDB will call with an arbitrary length (it can't know the real length and
82 will reply with chunks of XML that are easy for us to deal with. Gdb will
83 keep calling until we say we are done. XML doc looks like:
86 <library name="/a/a/c/d.dSYM"><segment address="0x10000000"/></library>
87 <library name="/a/m/e/e.pdb"><segment address="0x20000000"/></library>
88 <library name="/a/l/f/f.dll"><segment address="0x30000000"/></library>
91 Since we can not allocate memory in interupt context this module has
92 assumptions about how it will get called:
93 1) Length will generally be max remote packet size (big enough)
94 2) First Offset of an XML document read needs to be 0
95 3) This code will return back small chunks of the XML document on every read.
96 Each subseqent call will ask for the next available part of the document.
98 Note: The only variable size element in the XML is:
99 " <library name=\"%s\"><segment address=\"%p\"/></library>\n" and it is
100 based on the file path and name of the symbol file. If the symbol file name
101 is bigger than the max gdb remote packet size we could update this code
102 to respond back in chunks.
104 @param Offset offset into special data area
105 @param Length number of bytes to read starting at Offset
114 gPacketqXferLibraryOffset
+= gXferObjectReadResponse ('m', "<library-list>\n");
115 gPacketqXferLibraryOffset
+= gXferObjectReadResponse ('m', qXferHack
);
116 gXferObjectReadResponse ('l', "</library-list>\n");
117 gPacketqXferLibraryOffset
= 0;
121 Transfer length bytes of input buffer, starting at Address, to memory.
123 @param length the number of the bytes to be transferred/written
124 @param *address the start address of the transferring/writing the memory
125 @param *new_data the new data to be written to memory
129 TransferFromInBufToMem (
131 IN
unsigned char *Address
,
138 while (Length
-- > 0) {
139 c1
= (CHAR8
)HexCharToInt (*NewData
++);
140 c2
= (CHAR8
)HexCharToInt (*NewData
++);
142 if ((c1
< 0) || (c2
< 0)) {
143 SendError (GDB_EBADMEMDATA
);
146 *Address
++ = (UINT8
)((c1
<< 4) + c2
);
154 Transfer Length bytes of memory starting at Address to an output buffer, OutBuffer. This function will finally send the buffer
157 @param Length the number of the bytes to be transferred/read
158 @param *address pointer to the start address of the transferring/reading the memory
162 TransferFromMemToOutBufAndSend (
164 IN
unsigned char *Address
167 // there are Length bytes and every byte is represented as 2 hex chars
168 CHAR8 OutBuffer
[MAX_BUF_SIZE
];
169 CHAR8
*OutBufPtr
; // pointer to the output buffer
172 OutBufPtr
= OutBuffer
;
175 Char
= mHexToStr
[*Address
>> 4];
176 if ((Char
>= 'A') && (Char
<= 'F')) {
177 Char
= Char
- 'A' + 'a';
181 Char
= mHexToStr
[*Address
& 0x0f];
182 if ((Char
>= 'A') && (Char
<= 'F')) {
183 Char
= Char
- 'A' + 'a';
191 *OutBufPtr
= '\0' ; // the end of the buffer
192 SendPacket (OutBuffer
);
198 Send a GDB Remote Serial Protocol Packet
200 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
201 the packet teminating character '#' and the two digit checksum.
203 If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up
204 in an infinit loop. This is so if you unplug the debugger code just keeps running
206 @param PacketData Payload data for the packet
209 @retval Number of bytes of packet data sent.
223 Timeout
= PcdGet32 (PcdGdbMaxPacketRetryCount
);
230 if (Timeout
-- == 0) {
231 // Only try a finite number of times so we don't get stuck in the loop
238 for (CheckSum
= 0, Count
=0 ; *Ptr
!= '\0'; Ptr
++, Count
++) {
240 CheckSum
= CheckSum
+ *Ptr
;
243 // Packet terminating character and checksum
245 GdbPutChar (mHexToStr
[CheckSum
>> 4]);
246 GdbPutChar (mHexToStr
[CheckSum
& 0x0F]);
248 TestChar
= GdbGetChar ();
249 } while (TestChar
!= '+');
255 Receive a GDB Remote Serial Protocol Packet
257 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
258 the packet teminating character '#' and the two digit checksum.
260 If host re-starts sending a packet without ending the previous packet, only the last valid packet is processed.
261 (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)
263 If an ack '+' is not sent resend the packet
265 @param PacketData Payload data for the packet
267 @retval Number of bytes of packet data received.
272 OUT CHAR8
*PacketData
,
273 IN UINTN PacketDataSize
282 ZeroMem (PacketData
, PacketDataSize
);
285 // wait for the start of a packet
286 TestChar
= GdbGetChar ();
287 while (TestChar
!= '$') {
288 TestChar
= GdbGetChar ();
292 for (Index
= 0, CheckSum
= 0; Index
< (PacketDataSize
- 1); Index
++) {
293 Char
= GdbGetChar ();
301 PacketData
[Index
] = Char
;
302 CheckSum
= CheckSum
+ Char
;
304 PacketData
[Index
] = '\0';
306 if (Index
== PacketDataSize
) {
310 SumString
[0] = GdbGetChar ();
311 SumString
[1] = GdbGetChar ();
314 if (AsciiStrHexToUintn (SumString
) == CheckSum
) {
318 // Null terminate the callers string
319 PacketData
[Index
] = '\0';
332 Empties the given buffer
333 @param Buf pointer to the first element in buffer to be emptied
345 Converts an 8-bit Hex Char into a INTN.
347 @param Char the hex character to be converted into UINTN
348 @retval a INTN, from 0 to 15, that corressponds to Char
349 -1 if Char is not a hex character
356 if ((Char
>= 'A') && (Char
<= 'F')) {
357 return Char
- 'A' + 10;
358 } else if ((Char
>= 'a') && (Char
<= 'f')) {
359 return Char
- 'a' + 10;
360 } else if ((Char
>= '0') && (Char
<= '9')) {
362 } else { // if not a hex value, return a negative value
367 // 'E' + the biggest error number is 255, so its 2 hex digits + buffer end
368 CHAR8
*gError
= "E__";
371 Send an error with the given error number after converting to hex.
372 The error number is put into the buffer in hex. '255' is the biggest errno we can send.
373 ex: 162 will be sent as A2.
375 @param errno the error number that will be sent
384 // Replace _, or old data, with current errno
386 gError
[1] = mHexToStr
[ErrorNum
>> 4];
387 gError
[2] = mHexToStr
[ErrorNum
& 0x0f];
389 SendPacket (gError
); // send buffer
395 Send 'OK' when the function is done executing successfully.
403 SendPacket ("OK"); // send buffer
408 Send empty packet to specify that particular command/functionality is not supported.
424 Translates the EFI mapping to GDB mapping
426 @param EFIExceptionType EFI Exception that is being processed
427 @retval UINTN that corresponds to EFIExceptionType's GDB exception type number
430 ConvertEFItoGDBtype (
431 IN EFI_EXCEPTION_TYPE EFIExceptionType
436 for (i
=0; i
< MaxEfiException() ; i
++) {
437 if (gExceptionType
[i
].Exception
== EFIExceptionType
) {
438 return gExceptionType
[i
].SignalNo
;
441 return GDB_SIGTRAP
; // this is a GDB trap
446 Find the Length of the area to read and the start addres. Finally, pass them to
447 another function, TransferFromMemToOutBufAndSend, that will read from that memory space and
459 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
]; // the buffer that will hold the address in hex chars
460 CHAR8
*AddrBufPtr
; // pointer to the address buffer
461 CHAR8
*InBufPtr
; /// pointer to the input buffer
463 AddrBufPtr
= AddressBuffer
;
464 InBufPtr
= &PacketData
[1];
465 while (*InBufPtr
!= ',') {
466 *AddrBufPtr
++ = *InBufPtr
++;
470 InBufPtr
++; // this skips ',' in the buffer
473 if (AsciiStrLen(AddressBuffer
) >= MAX_ADDR_SIZE
) {
474 SendError (GDB_EBADMEMADDRBUFSIZE
);
479 if (AsciiStrLen(PacketData
) - AsciiStrLen(AddressBuffer
) - 2 >= MAX_LENGTH_SIZE
) {
480 SendError (GDB_EBADMEMLENGTH
);
484 Address
= AsciiStrHexToUintn (AddressBuffer
);
485 Length
= AsciiStrHexToUintn (InBufPtr
);
487 TransferFromMemToOutBufAndSend (Length
, (unsigned char *)Address
);
491 /** "M addr,length :XX..."
492 Find the Length of the area in bytes to write and the start addres. Finally, pass them to
493 another function, TransferFromInBufToMem, that will write to that memory space the info in
505 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
]; // the buffer that will hold the Address in hex chars
506 CHAR8 LengthBuffer
[MAX_LENGTH_SIZE
]; // the buffer that will hold the Length in hex chars
507 CHAR8
*AddrBufPtr
; // pointer to the Address buffer
508 CHAR8
*LengthBufPtr
; // pointer to the Length buffer
509 CHAR8
*InBufPtr
; /// pointer to the input buffer
511 AddrBufPtr
= AddressBuffer
;
512 LengthBufPtr
= LengthBuffer
;
513 InBufPtr
= &PacketData
[1];
515 while (*InBufPtr
!= ',') {
516 *AddrBufPtr
++ = *InBufPtr
++;
520 InBufPtr
++; // this skips ',' in the buffer
522 while (*InBufPtr
!= ':') {
523 *LengthBufPtr
++ = *InBufPtr
++;
525 *LengthBufPtr
= '\0';
527 InBufPtr
++; // this skips ':' in the buffer
529 Address
= AsciiStrHexToUintn (AddressBuffer
);
530 Length
= AsciiStrHexToUintn (LengthBuffer
);
534 //Check if Address is not too long.
535 if (AsciiStrLen(AddressBuffer
) >= MAX_ADDR_SIZE
) {
536 SendError (GDB_EBADMEMADDRBUFSIZE
);
540 //Check if message length is not too long
541 if (AsciiStrLen(LengthBuffer
) >= MAX_LENGTH_SIZE
) {
542 SendError (GDB_EBADMEMLENGBUFSIZE
);
546 // Check if Message is not too long/short.
547 // 3 = 'M' + ',' + ':'
548 MessageLength
= (AsciiStrLen(PacketData
) - AsciiStrLen(AddressBuffer
) - AsciiStrLen(LengthBuffer
) - 3);
549 if (MessageLength
!= (2*Length
)) {
550 //Message too long/short. New data is not the right size.
551 SendError (GDB_EBADMEMDATASIZE
);
554 TransferFromInBufToMem (Length
, (unsigned char *)Address
, InBufPtr
);
558 Parses breakpoint packet data and captures Breakpoint type, Address and length.
559 In case of an error, function returns particular error code. Returning 0 meaning
562 @param PacketData Pointer to the payload data for the packet.
563 @param Type Breakpoint type
564 @param Address Breakpoint address
565 @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
568 @retval {other} Particular error code
572 ParseBreakpointPacket (
573 IN CHAR8
*PacketData
,
579 CHAR8 AddressBuffer
[MAX_ADDR_SIZE
];
580 CHAR8
*AddressBufferPtr
;
581 CHAR8
*PacketDataPtr
;
583 PacketDataPtr
= &PacketData
[1];
584 AddressBufferPtr
= AddressBuffer
;
586 *Type
= AsciiStrHexToUintn (PacketDataPtr
);
588 //Breakpoint/watchpoint type should be between 0 to 4
590 return 22; //EINVAL: Invalid argument.
593 //Skip ',' in the buffer.
594 while (*PacketDataPtr
++ != ',');
596 //Parse Address information
597 while (*PacketDataPtr
!= ',') {
598 *AddressBufferPtr
++ = *PacketDataPtr
++;
600 *AddressBufferPtr
= '\0';
602 //Check if Address is not too long.
603 if (AsciiStrLen(AddressBuffer
) >= MAX_ADDR_SIZE
) {
604 return 40; //EMSGSIZE: Message size too long.
607 *Address
= AsciiStrHexToUintn (AddressBuffer
);
609 PacketDataPtr
++; //This skips , in the buffer
611 //Parse Length information
612 *Length
= AsciiStrHexToUintn (PacketDataPtr
);
614 //Length should be 1, 2 or 4 bytes
616 return 22; //EINVAL: Invalid argument
619 return 0; //0 = No error
625 Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints
627 @param SystemContext Register content at time of the exception
628 @param GdbExceptionType GDB exception type
632 IN EFI_SYSTEM_CONTEXT SystemContext
,
633 IN UINT8 GdbExceptionType
636 CHAR8 TSignalBuffer
[128];
639 TSignalPtr
= &TSignalBuffer
[0];
641 //Construct TSignal packet
645 // replace _, or previous value, with Exception type
647 *TSignalPtr
++ = mHexToStr
[GdbExceptionType
>> 4];
648 *TSignalPtr
++ = mHexToStr
[GdbExceptionType
& 0x0f];
650 ProcessorSendTSignal (SystemContext
, GdbExceptionType
, TSignalPtr
, sizeof (TSignalBuffer
) - 2);
652 SendPacket (TSignalBuffer
);
664 AsciiSPrint (Buffer
, sizeof (Buffer
), "Fwrite,%x,%x,%x", Fd
, Data
, DataSize
);
668 ReceivePacket (gInBuffer
, MAX_BUF_SIZE
);
670 switch (gInBuffer
[0]) {
672 ReadFromMemory (gInBuffer
);
676 WriteToMemory (gInBuffer
);
691 UINTN Len
= AsciiStrSize (String
);
693 GdbFWrite (2, String
, Len
);
698 Exception Hanldler for GDB. It will be called for all exceptions
699 registered via the gExceptionType[] array.
701 @param ExceptionType Exception that is being processed
702 @param SystemContext Register content at time of the exception
706 GdbExceptionHandler (
707 IN EFI_EXCEPTION_TYPE ExceptionType
,
708 IN OUT EFI_SYSTEM_CONTEXT SystemContext
711 UINT8 GdbExceptionType
;
714 if (ProcessorControlC (ExceptionType
, SystemContext
)) {
715 // We tried to process a control C handler and there is nothing to do
719 GdbExceptionType
= ConvertEFItoGDBtype (ExceptionType
);
720 GdbSendTSignal (SystemContext
, GdbExceptionType
);
723 ReceivePacket (gInBuffer
, MAX_BUF_SIZE
);
725 switch (gInBuffer
[0]) {
727 GdbSendTSignal (SystemContext
, GdbExceptionType
);
731 ContinueAtAddress (SystemContext
, gInBuffer
);
735 // gdb wants to disconnect so return "OK" packet since.
740 ReadGeneralRegisters (SystemContext
);
744 WriteGeneralRegisters (SystemContext
, gInBuffer
);
748 //Return "OK" packet since we don't have more than one thread.
753 ReadFromMemory (gInBuffer
);
757 WriteToMemory (gInBuffer
);
761 WriteNthRegister (SystemContext
, gInBuffer
);
765 // Still debugging this code. Not used in Darwin
768 // General Query Packets
769 if (AsciiStrnCmp (gInBuffer
, "qSupported", 10) == 0) {
770 // return what we currently support, we don't parse what gdb suports
771 AsciiSPrint (gOutBuffer
, MAX_BUF_SIZE
, "qXfer:libraries:read+;PacketSize=%d", MAX_BUF_SIZE
);
772 SendPacket (gOutBuffer
);
773 } else if (AsciiStrnCmp (gInBuffer
, "qXfer:libraries:read::", 22) == 0) {
774 // \91qXfer:libraries:read::offset,length
775 // gInBuffer[22] is offset string, ++Ptr is length string\92
776 for (Ptr
= &gInBuffer
[22]; *Ptr
!= ','; Ptr
++);
778 // Not sure if multi-radix support is required. Currently only support decimal
779 QxferLibrary (AsciiStrHexToUintn (&gInBuffer
[22]), AsciiStrHexToUintn (++Ptr
));
780 } else if (AsciiStrnCmp (gInBuffer
, "qOffsets", 8) == 0) {
781 AsciiSPrint (gOutBuffer
, MAX_BUF_SIZE
, "Text=1000;Data=f000;Bss=f000");
782 SendPacket (gOutBuffer
);
783 } else if (AsciiStrnCmp (gInBuffer
, "qAttached", 9) == 0) {
784 // remote server attached to an existing process
793 SingleStep (SystemContext
, gInBuffer
);
797 RemoveBreakPoint (SystemContext
, gInBuffer
);
801 InsertBreakPoint (SystemContext
, gInBuffer
);