12ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** @file 22ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Processor specific parts of the GDB stub 32ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 460274ccab831d7874129a6b6c271969418296960hhtian Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> 53402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 660274ccab831d7874129a6b6c271969418296960hhtian This program and the accompanying materials 72ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH are licensed and made available under the terms and conditions of the BSD License 82ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH which accompanies this distribution. The full text of the license may be found at 92ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH http://opensource.org/licenses/bsd-license.php 102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/ 152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#include <GdbStubInternal.h> 172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#include <Library/CacheMaintenanceLib.h> 182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#include <Library/PrintLib.h> 192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// 212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// Array of exception types that need to be hooked by the debugger 222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// (efi, gdb) //efi number 232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// 242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = { 252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH { EXCEPT_ARM_SOFTWARE_INTERRUPT, GDB_SIGTRAP } 263402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron// { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP }, 273402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron// { EXCEPT_ARM_PREFETCH_ABORT, GDB_SIGTRAP }, 283402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron// { EXCEPT_ARM_DATA_ABORT, GDB_SIGEMT }, 293402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron// { EXCEPT_ARM_RESERVED, GDB_SIGILL } 302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}; 312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// Shut up some annoying RVCT warnings 332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#ifdef __CC_ARM 342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#pragma diag_suppress 1296 352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#endif 362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN gRegisterOffsets[] = { 382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R0), 392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R1), 402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R2), 412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R3), 422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R4), 432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R5), 442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R6), 452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R7), 462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R8), 472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R9), 482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R10), 492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R11), 502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R12), 512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, SP), 522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, LR), 532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, PC), 542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F01, // f0 552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F02, 562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F03, 572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F11, // f1 582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F12, 592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F13, 602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F21, // f2 612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F22, 622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F23, 632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F31, // f3 642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F32, 652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F33, 662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F41, // f4 672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F42, 682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F43, 692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F51, // f5 702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F52, 712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F53, 722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F61, // f6 732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F62, 742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F63, 752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F71, // f7 762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F72, 772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000F73, 782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 0x00000FFF, // fps 792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, CPSR) 802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}; 812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// restore warnings for RVCT 832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#ifdef __CC_ARM 842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#pragma diag_default 1296 852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#endif 862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** 882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Return the number of entries in the gExceptionType[] 893402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 903402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @retval UINTN, the number of entries in the gExceptionType[] array. 912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN 932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHMaxEfiException ( 942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH VOID 952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 976f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin return sizeof (gExceptionType) / sizeof (EFI_EXCEPTION_TYPE_ENTRY); 982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** 1022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Return the number of entries in the gRegisters[] 1033402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 1043402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @retval UINTN, the number of entries (registers) in the gRegisters[] array. 1052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 1062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN 1072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHMaxRegisterCount ( 1082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH VOID 1092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 1102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 1116f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin return sizeof (gRegisterOffsets) / sizeof (UINTN); 1122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 1132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** 1163402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Check to see if the ISA is supported. 1172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ISA = Instruction Set Architecture 1182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1193402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @retval TRUE if Isa is supported 1202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/ 1222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN 1232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHCheckIsa ( 1242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa 1252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 1262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 1272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (Isa == IsaArm) { 1282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return TRUE; 1292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } else { 1302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return FALSE; 1312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 1322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 1332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** 1362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering 1372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH It is, by default, set to find the register pointer of the ARM member 1383402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @param SystemContext Register content at time of the exception 1392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param RegNumber The register to which we want to find a pointer 1402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @retval the pointer to the RegNumber-th pointer 1413402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron **/ 1422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN * 1436f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartinFindPointerToRegister ( 1442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 1453402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron IN UINTN RegNumber 1462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 1472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 1482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINT8 *TempPtr; 1492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ASSERT(gRegisterOffsets[RegNumber] < 0xF00); 1502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH TempPtr = ((UINT8 *)SystemContext.SystemContextArm) + gRegisterOffsets[RegNumber]; 1512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return (UINT32 *)TempPtr; 1522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 1532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** 1562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr 1572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param SystemContext Register content at time of the exception 1582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param RegNumber the number of the register that we want to read 1592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on. 1602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @retval the pointer to the next character of the output buffer that is available to be written on. 1612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 1622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHCHAR8 * 1632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBasicReadRegister ( 1642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 1652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN UINTN RegNumber, 1662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN CHAR8 *OutBufPtr 1672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 1682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 1692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN RegSize; 1702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH CHAR8 Char; 1713402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 1722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (gRegisterOffsets[RegNumber] > 0xF00) { 1736f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin AsciiSPrint (OutBufPtr, 9, "00000000"); 1742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OutBufPtr += 8; 1752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return OutBufPtr; 1762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 1772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH RegSize = 0; 1792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH while (RegSize < 32) { 1806f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin Char = mHexToStr[(UINT8)((*FindPointerToRegister (SystemContext, RegNumber) >> (RegSize+4)) & 0xf)]; 1812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if ((Char >= 'A') && (Char <= 'F')) { 1822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Char = Char - 'A' + 'a'; 1832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 1842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *OutBufPtr++ = Char; 1853402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 1866f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin Char = mHexToStr[(UINT8)((*FindPointerToRegister (SystemContext, RegNumber) >> RegSize) & 0xf)]; 1872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if ((Char >= 'A') && (Char <= 'F')) { 1882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Char = Char - 'A' + 'a'; 1892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 1902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *OutBufPtr++ = Char; 1913402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 1922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH RegSize = RegSize + 8; 1932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 1942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return OutBufPtr; 1952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 1962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 1972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 19811c20f4e06d252feaa65aa5e526686baf015762doliviermartin/** 1993402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Reads the n-th register's value into an output buffer and sends it as a packet 2002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param SystemContext Register content at time of the exception 2012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param InBuffer Pointer to the input buffer received from gdb server 2022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 2032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 2042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHReadNthRegister ( 2052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 2062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN CHAR8 *InBuffer 2072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 2082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 2092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN RegNumber; 2102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq) 2112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH CHAR8 *OutBufPtr; // pointer to the output buffer 2123402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH RegNumber = AsciiStrHexToUintn (&InBuffer[1]); 2143402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2156f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin if (RegNumber >= MaxRegisterCount ()) { 2163402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron SendError (GDB_EINVALIDREGNUM); 2172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 2182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 2193402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OutBufPtr = OutBuffer; 2212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr); 2223402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *OutBufPtr = '\0'; // the end of the buffer 2246f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin SendPacket (OutBuffer); 2252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 2262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 2272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 22811c20f4e06d252feaa65aa5e526686baf015762doliviermartin/** 2293402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Reads the general registers into an output buffer and sends it as a packet 2302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param SystemContext Register content at time of the exception 2312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 2322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 2332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI 2343402aac7d985bf8a9f9d3c639f3fe93609380513Ronald CronReadGeneralRegisters ( 2352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext 2362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 2372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 2382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN Index; 2392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH CHAR8 *OutBuffer; 2402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH CHAR8 *OutBufPtr; 2416f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin UINTN RegisterCount = MaxRegisterCount (); 2423402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // It is not safe to allocate pool here.... 2446f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin OutBuffer = AllocatePool ((RegisterCount * 8) + 1); // 8 bytes per register in string format plus a null to terminate 2452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OutBufPtr = OutBuffer; 2462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH for (Index = 0; Index < RegisterCount; Index++) { 2472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OutBufPtr = BasicReadRegister (SystemContext, Index, OutBufPtr); 2482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 2493402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *OutBufPtr = '\0'; 2516f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin SendPacket (OutBuffer); 2526f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin FreePool (OutBuffer); 2532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 2542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 2552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 2562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** 2572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr 2582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param SystemContext Register content at time of the exception 2592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param RegNumber the number of the register that we want to write 2602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on. 2612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @retval the pointer to the next character of the input buffer that can be used 2622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 2632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHCHAR8 2642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH*BasicWriteRegister ( 2652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 2662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN UINTN RegNumber, 2672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN CHAR8 *InBufPtr 2682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 2692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 2702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN RegSize; 2712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN TempValue; // the value transferred from a hex char 2722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINT32 NewValue; // the new value of the RegNumber-th Register 2733402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (gRegisterOffsets[RegNumber] > 0xF00) { 2752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return InBufPtr + 8; 2762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 2772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 2782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH NewValue = 0; 2792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH RegSize = 0; 2802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH while (RegSize < 32) { 2816f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin TempValue = HexCharToInt (*InBufPtr++); 2823402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if ((INTN)TempValue < 0) { 2843402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron SendError (GDB_EBADMEMDATA); 2852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return NULL; 2862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 2873402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH NewValue += (TempValue << (RegSize+4)); 2896f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin TempValue = HexCharToInt (*InBufPtr++); 2903402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if ((INTN)TempValue < 0) { 2923402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron SendError (GDB_EBADMEMDATA); 2932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return NULL; 2942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 2953402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 2963402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron NewValue += (TempValue << RegSize); 2972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH RegSize = RegSize + 8; 2982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 2996f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin *(FindPointerToRegister (SystemContext, RegNumber)) = NewValue; 3002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return InBufPtr; 3012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 3022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** ‘P n...=r...’ 3052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Writes the new value of n-th register received into the input buffer to the n-th register 3062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param SystemContext Register content at time of the exception 3072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param InBuffer Ponter to the input buffer received from gdb server 3082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 3092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 3102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHWriteNthRegister ( 3112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 3122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN CHAR8 *InBuffer 3132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 3142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 3152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN RegNumber; 3162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array 3172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH CHAR8 *RegNumBufPtr; 3182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH CHAR8 *InBufPtr; // pointer to the input buffer 3193402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 3202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // find the register number to write 3212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH InBufPtr = &InBuffer[1]; 3222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH RegNumBufPtr = RegNumBuffer; 3232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH while (*InBufPtr != '=') { 3242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *RegNumBufPtr++ = *InBufPtr++; 3253402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron } 3262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *RegNumBufPtr = '\0'; 3273402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron RegNumber = AsciiStrHexToUintn (RegNumBuffer); 3283402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 3292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // check if this is a valid Register Number 3306f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin if (RegNumber >= MaxRegisterCount ()) { 3313402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron SendError (GDB_EINVALIDREGNUM); 3322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 3332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 3342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH InBufPtr++; // skips the '=' character 3352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH BasicWriteRegister (SystemContext, RegNumber, InBufPtr); 3362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH SendSuccess(); 3372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 3382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** ‘G XX...’ 3412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Writes the new values received into the input buffer to the general registers 3422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param SystemContext Register content at time of the exception 3432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param InBuffer Pointer to the input buffer received from gdb server 3442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 3452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 3472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI 3482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHWriteGeneralRegisters ( 3492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 3502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN CHAR8 *InBuffer 3512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 3522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 3532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN i; 3542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH CHAR8 *InBufPtr; /// pointer to the input buffer 3552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN MinLength; 3566f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin UINTN RegisterCount = MaxRegisterCount (); 3572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH MinLength = (RegisterCount * 8) + 1; // 'G' plus the registers in ASCII format 3593402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 3606f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin if (AsciiStrLen (InBuffer) < MinLength) { 3613402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron //Bad message. Message is not the right length 3623402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron SendError (GDB_EBADBUFSIZE); 3632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 3642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 3653402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 3662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH InBufPtr = &InBuffer[1]; 3673402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 3682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // Read the new values for the registers from the input buffer to an array, NewValueArray. 3692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // The values in the array are in the gdb ordering 3706f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin for (i = 0; i < RegisterCount; i++) { 3712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr); 3722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 3733402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 3742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH SendSuccess (); 3752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 3762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// What about Thumb? 3782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// Use SWI 0xdbdbdb as the debug instruction 3792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#define GDB_ARM_BKPT 0xefdbdbdb 3802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN mSingleStepActive = FALSE; 3822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINT32 mSingleStepPC; 3832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINT32 mSingleStepData; 3842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN mSingleStepDataSize; 3852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHtypedef struct { 3872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH LIST_ENTRY Link; 3882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINT64 Signature; 3892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINT32 Address; 3902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINT32 Instruction; 3912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} ARM_SOFTWARE_BREAKPOINT; 3922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#define ARM_SOFTWARE_BREAKPOINT_SIGNATURE SIGNATURE_64('A', 'R', 'M', 'B', 'R', 'K', 'P', 'T') 3942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#define ARM_SOFTWARE_BREAKPOINT_FROM_LINK(a) CR(a, ARM_SOFTWARE_BREAKPOINT, Link, ARM_SOFTWARE_BREAKPOINT_SIGNATURE) 3952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHLIST_ENTRY BreakpointList; 3972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 3983402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron/** 3992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Insert Single Step in the SystemContext 4003402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 40191c38d4e94c1461f5824b83d3722fe46626aa0d3Ronald Cron @param SystemContext Register content at time of the exception 4022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 4032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 4042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHAddSingleStep ( 4052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext 4062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 4072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 4082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (mSingleStepActive) { 4092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // Currently don't support nesting 4102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 4112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 4122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH mSingleStepActive = TRUE; 4133402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 4142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH mSingleStepPC = SystemContext.SystemContextArm->PC; 4152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 4162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH mSingleStepDataSize = sizeof (UINT32); 4173402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron mSingleStepData = (*(UINT32 *)mSingleStepPC); 4182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *(UINT32 *)mSingleStepPC = GDB_ARM_BKPT; 4192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (*(UINT32 *)mSingleStepPC != GDB_ARM_BKPT) { 4202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // For some reason our breakpoint did not take 4212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH mSingleStepActive = FALSE; 4222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 4232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 4246f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin InvalidateInstructionCacheRange ((VOID *)mSingleStepPC, mSingleStepDataSize); 4252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH //DEBUG((EFI_D_ERROR, "AddSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, mSingleStepData, *(UINT32 *)mSingleStepPC)); 4262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 4272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 4283402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 4293402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron/** 4302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Remove Single Step in the SystemContext 4313402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 43291c38d4e94c1461f5824b83d3722fe46626aa0d3Ronald Cron @param SystemContext Register content at time of the exception 4332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 4342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 4352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHRemoveSingleStep ( 4362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext 4372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 4382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 4392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (!mSingleStepActive) { 4402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 4412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 4423402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 4432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (mSingleStepDataSize == sizeof (UINT16)) { 4442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *(UINT16 *)mSingleStepPC = (UINT16)mSingleStepData; 4452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } else { 4462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH //DEBUG((EFI_D_ERROR, "RemoveSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, *(UINT32 *)mSingleStepPC, mSingleStepData)); 4472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *(UINT32 *)mSingleStepPC = mSingleStepData; 4482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 4496f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin InvalidateInstructionCacheRange ((VOID *)mSingleStepPC, mSingleStepDataSize); 4502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH mSingleStepActive = FALSE; 4512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 4522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 4532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 4542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 45511c20f4e06d252feaa65aa5e526686baf015762doliviermartin/** 4563402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Continue. addr is Address to resume. If addr is omitted, resume at current 4572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Address. 4583402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 4593402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @param SystemContext Register content at time of the exception 4602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 4612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 4622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI 4632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHContinueAtAddress ( 4642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 4652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN CHAR8 *PacketData 4662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 4672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 4682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (PacketData[1] != '\0') { 4696f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin SystemContext.SystemContextArm->PC = AsciiStrHexToUintn (&PacketData[1]); 4703402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron } 4712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 4722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 4732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 4742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** ‘s [addr ]’ 4753402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Single step. addr is the Address at which to resume. If addr is omitted, resume 4762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH at same Address. 4773402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 4783402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @param SystemContext Register content at time of the exception 4792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/ 4802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 4812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI 4822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHSingleStep ( 4832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 4842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN CHAR8 *PacketData 4852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 4862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 4876f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin SendNotSupported (); 4882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 4892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 4902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN 4912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHGetBreakpointDataAddress ( 4922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 4932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN UINTN BreakpointNumber 4942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 4952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 4962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return 0; 4972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 4982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 4992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN 5002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHGetBreakpointDetected ( 5012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext 5022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 5032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 5042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return 0; 5052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 5062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBREAK_TYPE 5082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHGetBreakpointType ( 5092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 5102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN UINTN BreakpointNumber 5112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 5122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 5132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return NotSupported; 5142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 5152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHARM_SOFTWARE_BREAKPOINT * 5172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHSearchBreakpointList ( 5182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN UINT32 Address 5192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 5202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 5212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH LIST_ENTRY *Current; 5222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ARM_SOFTWARE_BREAKPOINT *Breakpoint; 5232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5246f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin Current = GetFirstNode (&BreakpointList); 5256f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin while (!IsNull (&BreakpointList, Current)) { 5262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Breakpoint = ARM_SOFTWARE_BREAKPOINT_FROM_LINK(Current); 5272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (Address == Breakpoint->Address) { 5292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return Breakpoint; 5302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 5312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5326f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin Current = GetNextNode (&BreakpointList, Current); 5332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 5342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return NULL; 5362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 5372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 5392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHSetBreakpoint ( 5402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN UINT32 Address 5412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 5422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 5432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ARM_SOFTWARE_BREAKPOINT *Breakpoint; 5442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5456f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin Breakpoint = SearchBreakpointList (Address); 5462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (Breakpoint != NULL) { 5482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 5492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 5502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // create and fill breakpoint structure 5526f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin Breakpoint = AllocatePool (sizeof(ARM_SOFTWARE_BREAKPOINT)); 5532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Breakpoint->Signature = ARM_SOFTWARE_BREAKPOINT_SIGNATURE; 5552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Breakpoint->Address = Address; 5562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Breakpoint->Instruction = *(UINT32 *)Address; 5573402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 5582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // Add it to the list 5596f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin InsertTailList (&BreakpointList, &Breakpoint->Link); 5602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // Insert the software breakpoint 5622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *(UINT32 *)Address = GDB_ARM_BKPT; 5636f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin InvalidateInstructionCacheRange ((VOID *)Address, 4); 5642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH //DEBUG((EFI_D_ERROR, "SetBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, Breakpoint->Instruction, *(UINT32 *)Address)); 5662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 5672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 5692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHClearBreakpoint ( 5702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN UINT32 Address 5712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 5722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 5732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ARM_SOFTWARE_BREAKPOINT *Breakpoint; 5742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5756f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin Breakpoint = SearchBreakpointList (Address); 5762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (Breakpoint == NULL) { 5782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 5792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 5802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // Add it to the list 5826f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin RemoveEntryList (&Breakpoint->Link); 5832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // Restore the original instruction 5852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH *(UINT32 *)Address = Breakpoint->Instruction; 5866f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin InvalidateInstructionCacheRange ((VOID *)Address, 4); 5872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH //DEBUG((EFI_D_ERROR, "ClearBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, GDB_ARM_BKPT, *(UINT32 *)Address)); 5892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5906f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin FreePool (Breakpoint); 5912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 5922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 5932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 5942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI 5952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHInsertBreakPoint ( 5962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 5972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN CHAR8 *PacketData 5982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 5992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 6002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN Type; 6012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN Address; 6022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN Length; 6032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN ErrorCode; 6042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6056f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length); 6062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (ErrorCode > 0) { 6072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH SendError ((UINT8)ErrorCode); 6082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 6092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 6102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH switch (Type) { 6122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH case 0: //Software breakpoint 6132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH break; 6142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH default : 6162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH DEBUG((EFI_D_ERROR, "Insert breakpoint default: %x\n", Type)); 6172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH SendError (GDB_EINVALIDBRKPOINTTYPE); 6182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 6192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 6202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6216f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin SetBreakpoint (Address); 6222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH SendSuccess (); 6242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 6252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 6272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI 6282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHRemoveBreakPoint ( 6292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN EFI_SYSTEM_CONTEXT SystemContext, 6302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN CHAR8 *PacketData 6312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 6322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 6332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN Type; 6342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN Address; 6352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN Length; 6362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINTN ErrorCode; 6372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH //Parse breakpoint packet data 6392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length); 6402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (ErrorCode > 0) { 6412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH SendError ((UINT8)ErrorCode); 6422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 6432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 6442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH switch (Type) { 6462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH case 0: //Software breakpoint 6472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH break; 6483402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 6492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH default: 6502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH SendError (GDB_EINVALIDBRKPOINTTYPE); 6512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return; 6522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 6532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6546f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin ClearBreakpoint (Address); 6552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH SendSuccess (); 6572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 6582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID 6602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHInitializeProcessor ( 6612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH VOID 6622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 6632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 6642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // Initialize breakpoint list 6656f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin InitializeListHead (&BreakpointList); 6662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 6672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN 6692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHValidateAddress ( 6702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN VOID *Address 6712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 6722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 6732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if ((UINT32)Address < 0x80000000) { 6742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return FALSE; 6752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } else { 6762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return TRUE; 6772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 6782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 6792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN 6812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHValidateException ( 6823402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron IN EFI_EXCEPTION_TYPE ExceptionType, 6833402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron IN OUT EFI_SYSTEM_CONTEXT SystemContext 6842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ) 6852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{ 6862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINT32 ExceptionAddress; 6872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH UINT32 Instruction; 6883402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 6892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // Is it a debugger SWI? 6902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ExceptionAddress = SystemContext.SystemContextArm->PC -= 4; 6912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Instruction = *(UINT32 *)ExceptionAddress; 6922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH if (Instruction != GDB_ARM_BKPT) { 6932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return FALSE; 6942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH } 6952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 6962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // Special for SWI-based exception handling. SWI sets up the context 6972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // to return to the instruction following the SWI instruction - NOT what we want 6982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH // for a debugger! 6992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH SystemContext.SystemContextArm->PC = ExceptionAddress; 7002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 7012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH return TRUE; 7022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} 7032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH 704