1 /** @file 2 3 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 13 **/ 14 15 #include "Edb.h" 16 17 CHAR16 *mBranchTypeStr[] = { 18 L"(CALL)", 19 L"(CALLEX)", 20 L"(RET)", 21 L"(JMP)", 22 L"(JMP8)", 23 }; 24 25 /** 26 27 Comvert Branch Type to string. 28 29 @param Type Branch Type 30 31 @retval String string of Branch Type. 32 33 **/ 34 CHAR16 * 35 EdbBranchTypeToStr ( 36 IN EFI_DEBUGGER_BRANCH_TYPE Type 37 ) 38 { 39 if (Type < 0 || Type >= EfiDebuggerBranchTypeEbcMax) { 40 return L"(Unknown Type)"; 41 } 42 43 return mBranchTypeStr [Type]; 44 } 45 46 /** 47 48 DebuggerCommand - CallStack. 49 50 @param CommandArg The argument for this command 51 @param DebuggerPrivate EBC Debugger private data structure 52 @param ExceptionType Exception type. 53 @param SystemContext EBC system context. 54 55 @retval EFI_DEBUG_CONTINUE formal return value 56 57 **/ 58 EFI_DEBUG_STATUS 59 DebuggerCallStack ( 60 IN CHAR16 *CommandArg, 61 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, 62 IN EFI_EXCEPTION_TYPE ExceptionType, 63 IN OUT EFI_SYSTEM_CONTEXT SystemContext 64 ) 65 { 66 INTN Index; 67 UINTN SubIndex; 68 CHAR8 *FuncName; 69 EFI_DEBUGGER_CALLSTACK_CONTEXT *CallStackEntry; 70 BOOLEAN ShowParameter; 71 UINTN ParameterNumber; 72 73 ShowParameter = FALSE; 74 ParameterNumber = EFI_DEBUGGER_CALL_DEFAULT_PARAMETER; 75 76 // 77 // Check argument 78 // 79 if (CommandArg != NULL) { 80 if (StriCmp (CommandArg, L"c") == 0) { 81 // 82 // Clear Call-Stack 83 // 84 DebuggerPrivate->CallStackEntryCount = 0; 85 ZeroMem (DebuggerPrivate->CallStackEntry, sizeof(DebuggerPrivate->CallStackEntry)); 86 EDBPrint (L"Call-Stack is cleared\n"); 87 return EFI_DEBUG_CONTINUE; 88 } else if (StriCmp (CommandArg, L"p") == 0) { 89 // 90 // Print Call-Stack with parameter 91 // 92 ShowParameter = TRUE; 93 CommandArg = StrGetNextTokenLine (L" "); 94 if (CommandArg != NULL) { 95 // 96 // Try to get the parameter number 97 // 98 ParameterNumber = Atoi (CommandArg); 99 if (ParameterNumber > 16) { 100 EDBPrint (L"Call-Stack argument Invalid\n"); 101 return EFI_DEBUG_CONTINUE; 102 } 103 } 104 } else { 105 EDBPrint (L"Call-Stack argument Invalid\n"); 106 return EFI_DEBUG_CONTINUE; 107 } 108 } 109 110 // 111 // Check CallStack Entry Count 112 // 113 if (DebuggerPrivate->CallStackEntryCount == 0) { 114 EDBPrint (L"No Call-Stack\n"); 115 return EFI_DEBUG_CONTINUE; 116 } else if (DebuggerPrivate->CallStackEntryCount > EFI_DEBUGGER_CALLSTACK_MAX) { 117 EDBPrint (L"Call-Stack Crash, re-initialize!\n"); 118 DebuggerPrivate->CallStackEntryCount = 0; 119 return EFI_DEBUG_CONTINUE; 120 } 121 122 // 123 // Go through each CallStack entry and print 124 // 125 EDBPrint (L"Call-Stack (TOP):\n"); 126 EDBPrint (L" Caller Callee Name\n"); 127 EDBPrint (L" ================== ================== ========\n"); 128 //EDBPrint (L" 0x00000000FFFFFFFF 0xFFFFFFFF00000000 EfiMain\n"); 129 for (Index = (INTN)(DebuggerPrivate->CallStackEntryCount - 1); Index >= 0; Index--) { 130 // 131 // Get CallStack and print 132 // 133 CallStackEntry = &DebuggerPrivate->CallStackEntry[Index]; 134 EDBPrint ( 135 L" 0x%016lx 0x%016lx", 136 CallStackEntry->SourceAddress, 137 CallStackEntry->DestAddress 138 ); 139 FuncName = FindSymbolStr ((UINTN)CallStackEntry->DestAddress); 140 if (FuncName != NULL) { 141 EDBPrint (L" %a()", FuncName); 142 } 143 EDBPrint (L"\n"); 144 145 if (ShowParameter) { 146 // 147 // Print parameter 148 // 149 if (sizeof(UINTN) == sizeof(UINT64)) { 150 EDBPrint ( 151 L" Parameter Address (0x%016lx) (\n", 152 CallStackEntry->ParameterAddr 153 ); 154 if (ParameterNumber == 0) { 155 EDBPrint (L" )\n"); 156 continue; 157 } 158 // 159 // Print each parameter 160 // 161 for (SubIndex = 0; SubIndex < ParameterNumber - 1; SubIndex++) { 162 if (SubIndex % 2 == 0) { 163 EDBPrint (L" "); 164 } 165 EDBPrint ( 166 L"0x%016lx, ", 167 CallStackEntry->Parameter[SubIndex] 168 ); 169 if (SubIndex % 2 == 1) { 170 EDBPrint (L"\n"); 171 } 172 } 173 if (SubIndex % 2 == 0) { 174 EDBPrint (L" "); 175 } 176 EDBPrint ( 177 L"0x%016lx\n", 178 CallStackEntry->Parameter[SubIndex] 179 ); 180 EDBPrint (L" )\n"); 181 // 182 // break only for parameter 183 // 184 if ((((DebuggerPrivate->CallStackEntryCount - Index) % (16 / ParameterNumber)) == 0) && 185 (Index != 0)) { 186 if (SetPageBreak ()) { 187 break; 188 } 189 } 190 } else { 191 EDBPrint ( 192 L" Parameter Address (0x%08x) (\n", 193 CallStackEntry->ParameterAddr 194 ); 195 if (ParameterNumber == 0) { 196 EDBPrint (L" )\n"); 197 continue; 198 } 199 // 200 // Print each parameter 201 // 202 for (SubIndex = 0; SubIndex < ParameterNumber - 1; SubIndex++) { 203 if (SubIndex % 4 == 0) { 204 EDBPrint (L" "); 205 } 206 EDBPrint ( 207 L"0x%08x, ", 208 CallStackEntry->Parameter[SubIndex] 209 ); 210 if (SubIndex % 4 == 3) { 211 EDBPrint (L"\n"); 212 } 213 } 214 if (SubIndex % 4 == 0) { 215 EDBPrint (L" "); 216 } 217 EDBPrint ( 218 L"0x%08x\n", 219 CallStackEntry->Parameter[SubIndex] 220 ); 221 EDBPrint (L" )\n"); 222 // 223 // break only for parameter 224 // 225 if ((((DebuggerPrivate->CallStackEntryCount - Index) % (32 / ParameterNumber)) == 0) && 226 (Index != 0)) { 227 if (SetPageBreak ()) { 228 break; 229 } 230 } 231 } 232 } 233 } 234 235 // 236 // Done 237 // 238 return EFI_DEBUG_CONTINUE; 239 } 240 241 /** 242 243 DebuggerCommand - InstructionBranch. 244 245 @param CommandArg The argument for this command 246 @param DebuggerPrivate EBC Debugger private data structure 247 @param ExceptionType Exception type. 248 @param SystemContext EBC system context. 249 250 @retval EFI_DEBUG_CONTINUE formal return value 251 252 **/ 253 EFI_DEBUG_STATUS 254 DebuggerInstructionBranch ( 255 IN CHAR16 *CommandArg, 256 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, 257 IN EFI_EXCEPTION_TYPE ExceptionType, 258 IN OUT EFI_SYSTEM_CONTEXT SystemContext 259 ) 260 { 261 UINTN Index; 262 263 // 264 // Check argument 265 // 266 if (CommandArg != NULL) { 267 if (StriCmp (CommandArg, L"c") == 0) { 268 // 269 // Clear Trace 270 // 271 DebuggerPrivate->TraceEntryCount = 0; 272 ZeroMem (DebuggerPrivate->TraceEntry, sizeof(DebuggerPrivate->TraceEntry)); 273 EDBPrint (L"Instruction Trace is cleared\n"); 274 } else { 275 EDBPrint (L"Trace argument Invalid\n"); 276 } 277 return EFI_DEBUG_CONTINUE; 278 } 279 280 // 281 // Check Trace Entry Count 282 // 283 if (DebuggerPrivate->TraceEntryCount == 0) { 284 EDBPrint (L"No Instruction Trace\n"); 285 return EFI_DEBUG_CONTINUE; 286 } else if (DebuggerPrivate->TraceEntryCount > EFI_DEBUGGER_TRACE_MAX) { 287 EDBPrint (L"Instruction Trace Crash, re-initialize!\n"); 288 DebuggerPrivate->TraceEntryCount = 0; 289 return EFI_DEBUG_CONTINUE; 290 } 291 292 // 293 // Go through each Trace entry and print 294 // 295 EDBPrint (L"Instruction Trace (->Latest):\n"); 296 EDBPrint (L" Source Addr Destination Addr Type\n"); 297 EDBPrint (L" ================== ================== ========\n"); 298 //EDBPrint (L" 0x00000000FFFFFFFF 0xFFFFFFFF00000000 (CALLEX)\n"); 299 for (Index = 0; Index < DebuggerPrivate->TraceEntryCount; Index++) { 300 EDBPrint ( 301 L" 0x%016lx 0x%016lx %s\n", 302 DebuggerPrivate->TraceEntry[Index].SourceAddress, 303 DebuggerPrivate->TraceEntry[Index].DestAddress, 304 EdbBranchTypeToStr (DebuggerPrivate->TraceEntry[Index].Type) 305 ); 306 } 307 308 // 309 // Done 310 // 311 return EFI_DEBUG_CONTINUE; 312 } 313