/** Find the command according to name. @param CommandName - Command Name @param CommandArg - Command Argument @return Not NULL - The DebuggerCommand is found successfully @return NULL - not found **/ EFI_DEBUGGER_COMMAND MatchDebuggerCommand ( IN CHAR16 *CommandName, IN CHAR16 **CommandArg ) { UINTN Index; CHAR16 *Temp; // // Get Command Name // Temp = StrGetNewTokenLine (CommandName, L" "); CommandName = Temp; // // Get Command Argument // Temp = StrGetNextTokenLine (L" "); *CommandArg = Temp; if (CommandName == NULL) { return NULL; } // // Go through each command, check the CommandName // for (Index = 0; mDebuggerCommandSet[Index].CommandName != NULL; Index++) { if (StriCmp (CommandName, mDebuggerCommandSet[Index].CommandName) == 0) { // // Found // return mDebuggerCommandSet[Index].CommandFunc; } } // // Not found // return NULL; }
EFI_DEBUG_STATUS DebuggerCallStack ( IN CHAR16 *CommandArg, IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, IN EFI_EXCEPTION_TYPE ExceptionType, IN OUT EFI_SYSTEM_CONTEXT SystemContext ) /*++ Routine Description: DebuggerCommand - CallStack Arguments: CommandArg - The argument for this command DebuggerPrivate - EBC Debugger private data structure InterruptType - Interrupt type. SystemContext - EBC system context. Returns: EFI_DEBUG_CONTINUE - formal return value --*/ { INTN Index; UINTN SubIndex; CHAR8 *FuncName; EFI_DEBUGGER_CALLSTACK_CONTEXT *CallStackEntry; BOOLEAN ShowParameter; UINTN ParameterNumber; ShowParameter = FALSE; ParameterNumber = EFI_DEBUGGER_CALL_DEFAULT_PARAMETER; // // Check argument // if (CommandArg != NULL) { if (EfiStriCmp (CommandArg, L"c") == 0) { // // Clear Call-Stack // DebuggerPrivate->CallStackEntryCount = 0; EfiZeroMem (DebuggerPrivate->CallStackEntry, sizeof(DebuggerPrivate->CallStackEntry)); EDBPrint (L"Call-Stack is cleared\n"); return EFI_DEBUG_CONTINUE; } else if (EfiStriCmp (CommandArg, L"p") == 0) { // // Print Call-Stack with parameter // ShowParameter = TRUE; CommandArg = StrGetNextTokenLine (L" "); if (CommandArg != NULL) { // // Try to get the parameter number // ParameterNumber = Atoi (CommandArg); if (ParameterNumber > 16) { EDBPrint (L"Call-Stack argument Invalid\n"); return EFI_DEBUG_CONTINUE; } } } else { EDBPrint (L"Call-Stack argument Invalid\n"); return EFI_DEBUG_CONTINUE; } } // // Check CallStack Entry Count // if (DebuggerPrivate->CallStackEntryCount == 0) { EDBPrint (L"No Call-Stack\n"); return EFI_DEBUG_CONTINUE; } else if (DebuggerPrivate->CallStackEntryCount > EFI_DEBUGGER_CALLSTACK_MAX) { EDBPrint (L"Call-Stack Crash, re-initialize!\n"); DebuggerPrivate->CallStackEntryCount = 0; return EFI_DEBUG_CONTINUE; } // // Go through each CallStack entry and print // EDBPrint (L"Call-Stack (TOP):\n"); EDBPrint (L" Caller Callee Name\n"); EDBPrint (L" ================== ================== ========\n"); //EDBPrint (L" 0x00000000FFFFFFFF 0xFFFFFFFF00000000 EfiMain\n"); for (Index = (INTN)(DebuggerPrivate->CallStackEntryCount - 1); Index >= 0; Index--) { // // Get CallStack and print // CallStackEntry = &DebuggerPrivate->CallStackEntry[Index]; EDBPrint ( L" 0x%016lx 0x%016lx", CallStackEntry->SourceAddress, CallStackEntry->DestAddress ); FuncName = FindSymbolStr ((UINTN)CallStackEntry->DestAddress); if (FuncName != NULL) { EDBPrint (L" %a()", FuncName); } EDBPrint (L"\n"); if (ShowParameter) { // // Print parameter // if (sizeof(UINTN) == sizeof(UINT64)) { EDBPrint ( L" Parameter Address (0x%016lx) (\n", CallStackEntry->ParameterAddr ); if (ParameterNumber == 0) { EDBPrint (L" )\n"); continue; } // // Print each parameter // for (SubIndex = 0; SubIndex < ParameterNumber - 1; SubIndex++) { if (SubIndex % 2 == 0) { EDBPrint (L" "); } EDBPrint ( L"0x%016lx, ", CallStackEntry->Parameter[SubIndex] ); if (SubIndex % 2 == 1) { EDBPrint (L"\n"); } } if (SubIndex % 2 == 0) { EDBPrint (L" "); } EDBPrint ( L"0x%016lx\n", CallStackEntry->Parameter[SubIndex] ); EDBPrint (L" )\n"); // // break only for parameter // if ((((DebuggerPrivate->CallStackEntryCount - Index) % (16 / ParameterNumber)) == 0) && (Index != 0)) { if (SetPageBreak ()) { break; } } } else { EDBPrint ( L" Parameter Address (0x%08x) (\n", CallStackEntry->ParameterAddr ); if (ParameterNumber == 0) { EDBPrint (L" )\n"); continue; } // // Print each parameter // for (SubIndex = 0; SubIndex < ParameterNumber - 1; SubIndex++) { if (SubIndex % 4 == 0) { EDBPrint (L" "); } EDBPrint ( L"0x%08x, ", CallStackEntry->Parameter[SubIndex] ); if (SubIndex % 4 == 3) { EDBPrint (L"\n"); } } if (SubIndex % 4 == 0) { EDBPrint (L" "); } EDBPrint ( L"0x%08x\n", CallStackEntry->Parameter[SubIndex] ); EDBPrint (L" )\n"); // // break only for parameter // if ((((DebuggerPrivate->CallStackEntryCount - Index) % (32 / ParameterNumber)) == 0) && (Index != 0)) { if (SetPageBreak ()) { break; } } } } } // // Done // return EFI_DEBUG_CONTINUE; }
/** The default Exception Callback for the VM interpreter. In this function, we report status code, and print debug information about EBC_CONTEXT, then dead loop. @param ExceptionType Exception type. @param SystemContext EBC system context. **/ VOID EFIAPI EdbExceptionHandler ( IN EFI_EXCEPTION_TYPE ExceptionType, IN OUT EFI_SYSTEM_CONTEXT SystemContext ) { CHAR16 InputBuffer[EFI_DEBUG_INPUS_BUFFER_SIZE]; CHAR16 *CommandArg; EFI_DEBUGGER_COMMAND DebuggerCommand; EFI_DEBUG_STATUS DebugStatus; STATIC BOOLEAN mInitialized; mInitialized = FALSE; DEBUG ((DEBUG_ERROR, "Hello EBC Debugger!\n")); if (!mInitialized) { // // Print version // EDBPrint ( L"EBC Interpreter Version - %d.%d\n", (UINTN)VM_MAJOR_VERSION, (UINTN)VM_MINOR_VERSION ); EDBPrint ( L"EBC Debugger Version - %d.%d\n", (UINTN)EBC_DEBUGGER_MAJOR_VERSION, (UINTN)EBC_DEBUGGER_MINOR_VERSION ); } // // Init Private Data // InitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized); // // EDBPrint basic info // PrintExceptionReason (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized); EdbShowDisasm (&mDebuggerPrivate, SystemContext); // EFI_BREAKPOINT (); if (!mInitialized) { // // Interactive with user // EDBPrint (L"\nPlease enter command now, \'h\' for help.\n"); EDBPrint (L"(Using <Command> -b <...> to enable page break.)\n"); } mInitialized = TRUE; // // Dispatch each command // while (TRUE) { // // Get user input // Input (L"\n\r" EFI_DEBUG_PROMPT_STRING, InputBuffer, EFI_DEBUG_INPUS_BUFFER_SIZE); EDBPrint (L"\n"); // // Get command // DebuggerCommand = MatchDebuggerCommand (InputBuffer, &CommandArg); if (DebuggerCommand == NULL) { EDBPrint (L"ERROR: Command not found!\n"); continue; } // // Check PageBreak; // if (CommandArg != NULL) { if (StriCmp (CommandArg, L"-b") == 0) { CommandArg = StrGetNextTokenLine (L" "); mDebuggerPrivate.EnablePageBreak = TRUE; } } // // Dispatch command // DebugStatus = DebuggerCommand (CommandArg, &mDebuggerPrivate, ExceptionType, SystemContext); mDebuggerPrivate.EnablePageBreak = FALSE; // // Check command return status // if (DebugStatus == EFI_DEBUG_RETURN) { mInitialized = FALSE; break; } else if (DebugStatus == EFI_DEBUG_BREAK) { break; } else if (DebugStatus == EFI_DEBUG_CONTINUE) { continue; } else { ASSERT (FALSE); } } // // Deinit Private Data // DeinitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized); DEBUG ((DEBUG_ERROR, "Goodbye EBC Debugger!\n")); return; }
EFI_DEBUG_STATUS DebuggerGo ( IN CHAR16 *CommandArg, IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, IN EFI_EXCEPTION_TYPE ExceptionType, IN OUT EFI_SYSTEM_CONTEXT SystemContext ) /*++ Routine Description: DebuggerCommand - Go Arguments: CommandArg - The argument for this command DebuggerPrivate - EBC Debugger private data structure InterruptType - Interrupt type. SystemContext - EBC system context. Returns: EFI_DEBUG_BREAK - formal return value EFI_DEBUG_CONTINUE - something wrong --*/ { UINTN Address; CHAR16 *CommandStr; EFI_STATUS Status; // // Check argument // if (CommandArg != NULL) { if (EfiStriCmp (CommandArg, L"til") == 0) { CommandStr = StrGetNextTokenLine (L" "); if (CommandStr != NULL) { // // Enable GoTil break now // set BreakAddress, and set feature flag. // Status = Symboltoi (CommandStr, &Address); if (EFI_ERROR (Status)) { if (Status == EFI_NOT_FOUND) { Address = Xtoi(CommandStr); } else { // // Something wrong, let Symboltoi print error info. // EDBPrint (L"Command Argument error!\n"); return EFI_DEBUG_CONTINUE; } } DebuggerPrivate->GoTilContext.BreakAddress = Address; DebuggerPrivate->FeatureFlags |= EFI_DEBUG_FLAG_EBC_GT; } else { EDBPrint (L"Command Argument error!\n"); return EFI_DEBUG_CONTINUE; } } else { EDBPrint (L"Command Argument error!\n"); return EFI_DEBUG_CONTINUE; } } // // Done // return EFI_DEBUG_BREAK; }
EFI_STATUS EdbGetMemoryAddressValue ( IN CHAR16 *CommandArg, IN UINTN *Address, IN UINT64 *Value ) /*++ Routine Description: Get memory address and value Arguments: CommandArg - The argument for this command Address - Memory Address Value - Memory Value Returns: EFI_SUCCESS - memory address and value are got EFI_INVALID_PARAMETER - something wrong --*/ { CHAR16 *CommandStr; UINTN MemAddress; EFI_STATUS Status; // // Get Address // CommandStr = CommandArg; if (CommandStr == NULL) { EDBPrint (L"Memory: Address error!\n"); return EFI_INVALID_PARAMETER; } Status = Symboltoi (CommandStr, &MemAddress); if (EFI_ERROR (Status)) { if (Status == EFI_NOT_FOUND) { MemAddress = Xtoi(CommandStr); } else { // // Something wrong, let Symboltoi print error info. // EDBPrint (L"Command Argument error!\n"); return EFI_INVALID_PARAMETER; } } *Address = MemAddress; // // Get Value // CommandStr = StrGetNextTokenLine (L" "); if (CommandStr == NULL) { EDBPrint (L"Memory: Value error!\n"); return EFI_INVALID_PARAMETER; } *Value = LXtoi(CommandStr); // // Done // return EFI_SUCCESS; }