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