/*! \brief Print address... * * Tries to lookup line number, file name and function name for the given * address and prints it. * If no such information is found the address is printed in the format * <module: offset>, otherwise the format will be * <module: offset (filename:linenumber (functionname))> * * \retval TRUE Module containing \a Address was found, \a Address was printed. * \retval FALSE No module containing \a Address was found, nothing was printed. */ BOOLEAN KdbSymPrintAddress( IN PVOID Address, IN PKTRAP_FRAME Context) { PLDR_DATA_TABLE_ENTRY LdrEntry; ULONG_PTR RelativeAddress; NTSTATUS Status; ULONG LineNumber; CHAR FileName[256]; CHAR FunctionName[256]; CHAR ModuleNameAnsi[64]; if (!KdbpSymbolsInitialized || !KdbpSymFindModule(Address, NULL, -1, &LdrEntry)) return FALSE; KdbpSymUnicodeToAnsi(&LdrEntry->BaseDllName, ModuleNameAnsi, sizeof(ModuleNameAnsi)); RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase; Status = KdbSymGetAddressInformation(LdrEntry->PatchInformation, RelativeAddress, &LineNumber, FileName, FunctionName); if (NT_SUCCESS(Status)) { DbgPrint("<%s:%x (%s:%d (%s))>", ModuleNameAnsi, RelativeAddress, FileName, LineNumber, FunctionName); } else { DbgPrint("<%s:%x>", ModuleNameAnsi, RelativeAddress); } return TRUE; }
BOOLEAN NTAPI KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN SecondChance) { KD_CONTINUE_TYPE Return = kdHandleException; ULONG ExceptionCommand = ExceptionRecord->ExceptionInformation[0]; /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */ if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && (ExceptionRecord->NumberParameters > 0) && ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) || (ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) || (ExceptionCommand == BREAKPOINT_COMMAND_STRING) || (ExceptionCommand == BREAKPOINT_PRINT) || (ExceptionCommand == BREAKPOINT_PROMPT))) { /* Check if this is a debug print */ if (ExceptionCommand == BREAKPOINT_PRINT) { /* Print the string */ KdpServiceDispatcher(BREAKPOINT_PRINT, (PVOID)ExceptionRecord->ExceptionInformation[1], ExceptionRecord->ExceptionInformation[2]); /* Return success */ KeSetContextReturnRegister(Context, STATUS_SUCCESS); } #ifdef KDBG else if (ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) { PLDR_DATA_TABLE_ENTRY LdrEntry; /* Load symbols. Currently implemented only for KDBG! */ if(KdbpSymFindModule(((PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2])->BaseOfDll, NULL, -1, &LdrEntry)) KdbSymProcessSymbols(LdrEntry); } else if (ExceptionCommand == BREAKPOINT_PROMPT) { ULONG ReturnValue; LPSTR OutString; USHORT OutStringLength; /* Get the response string and length */ OutString = (LPSTR)Context->Ebx; OutStringLength = (USHORT)Context->Edi; /* Call KDBG */ ReturnValue = KdpPrompt((LPSTR)ExceptionRecord-> ExceptionInformation[1], (USHORT)ExceptionRecord-> ExceptionInformation[2], OutString, OutStringLength); /* Return the number of characters that we received */ Context->Eax = ReturnValue; } #endif /* This we can handle: simply bump the Program Counter */ KeSetContextPc(Context, KeGetContextPc(Context) + KD_BREAKPOINT_SIZE); return TRUE; } #ifdef KDBG /* Check if this is an assertion failure */ if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE) { /* Bump EIP to the instruction following the int 2C */ Context->Eip += 2; } #endif /* Get out of here if the Debugger isn't connected */ if (KdDebuggerNotPresent) return FALSE; #ifdef KDBG /* Call KDBG if available */ Return = KdbEnterDebuggerException(ExceptionRecord, PreviousMode, Context, TrapFrame, !SecondChance); #else /* not KDBG */ if (WrapperInitRoutine) { /* Call GDB */ Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord, Context, TrapFrame); } #endif /* not KDBG */ /* Debugger didn't handle it, please handle! */ if (Return == kdHandleException) return FALSE; /* Debugger handled it */ return TRUE; }
/*! \brief Print address... * * Tries to lookup line number, file name and function name for the given * address and prints it. * If no such information is found the address is printed in the format * <module: offset>, otherwise the format will be * <module: offset (filename:linenumber (functionname))> * * \retval TRUE Module containing \a Address was found, \a Address was printed. * \retval FALSE No module containing \a Address was found, nothing was printed. */ BOOLEAN KdbSymPrintAddress( IN PVOID Address, IN PKTRAP_FRAME Context) { int i; PMEMORY_AREA MemoryArea = NULL; PROS_SECTION_OBJECT SectionObject; PLDR_DATA_TABLE_ENTRY LdrEntry; #if 0 PROSSYM_KM_OWN_CONTEXT FileContext; #endif ULONG_PTR RelativeAddress; NTSTATUS Status; ROSSYM_LINEINFO LineInfo = {0}; struct { enum _ROSSYM_REGNAME regname; size_t ctx_offset; } regmap[] = { { ROSSYM_X86_EDX, FIELD_OFFSET(KTRAP_FRAME, Edx) }, { ROSSYM_X86_EAX, FIELD_OFFSET(KTRAP_FRAME, Eax) }, { ROSSYM_X86_ECX, FIELD_OFFSET(KTRAP_FRAME, Ecx) }, { ROSSYM_X86_EBX, FIELD_OFFSET(KTRAP_FRAME, Ebx) }, { ROSSYM_X86_ESI, FIELD_OFFSET(KTRAP_FRAME, Esi) }, { ROSSYM_X86_EDI, FIELD_OFFSET(KTRAP_FRAME, Edi) }, { ROSSYM_X86_EBP, FIELD_OFFSET(KTRAP_FRAME, Ebp) }, { ROSSYM_X86_ESP, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp) } }; if (Context) { #if 0 // Disable arguments for now DPRINT("Has Context %x (EBP %x)\n", Context, Context->Ebp); LineInfo.Flags = ROSSYM_LINEINFO_HAS_REGISTERS; #endif for (i = 0; i < sizeof(regmap) / sizeof(regmap[0]); i++) { memcpy (&LineInfo.Registers.Registers[regmap[i].regname], ((PCHAR)Context)+regmap[i].ctx_offset, sizeof(ULONG_PTR)); DPRINT("DWARF REG[%d] -> %x\n", regmap[i].regname, LineInfo.Registers.Registers[regmap[i].regname]); } } if (!KdbpSymbolsInitialized || !KdbpSymFindModule(Address, NULL, -1, &LdrEntry)) return FALSE; RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase; Status = KdbSymGetAddressInformation (LdrEntry->PatchInformation, RelativeAddress, &LineInfo); if (NT_SUCCESS(Status)) { DbgPrint("<%wZ:%x (%s:%d (%s))>", &LdrEntry->BaseDllName, RelativeAddress, LineInfo.FileName, LineInfo.LineNumber, LineInfo.FunctionName); if (Context && LineInfo.NumParams) { int i; char *comma = ""; DbgPrint("("); for (i = 0; i < LineInfo.NumParams; i++) { DbgPrint ("%s%s=%llx", comma, LineInfo.Parameters[i].ValueName, LineInfo.Parameters[i].Value); comma = ","; } DbgPrint(")"); } return TRUE; } else if (Address < MmSystemRangeStart) { MemoryArea = MmLocateMemoryAreaByAddress(&PsGetCurrentProcess()->Vm, Address); if (!MemoryArea || MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) { goto end; } SectionObject = MemoryArea->Data.SectionData.Section; if (!(SectionObject->AllocationAttributes & SEC_IMAGE)) goto end; #if 0 if (MemoryArea->StartingAddress != (PVOID)KdbpImageBase) { if (KdbpRosSymInfo) { RosSymDelete(KdbpRosSymInfo); KdbpRosSymInfo = NULL; KdbpImageBase = 0; } if ((FileContext = KdbpCaptureFileForSymbols(SectionObject->FileObject))) { if (RosSymCreateFromFile(FileContext, &KdbpRosSymInfo)) KdbpImageBase = (ULONG_PTR)MemoryArea->StartingAddress; KdbpReleaseFileForSymbols(FileContext); } } if (KdbpRosSymInfo) { RelativeAddress = (ULONG_PTR)Address - KdbpImageBase; RosSymFreeInfo(&LineInfo); Status = KdbSymGetAddressInformation (KdbpRosSymInfo, RelativeAddress, &LineInfo); if (NT_SUCCESS(Status)) { DbgPrint ("<%wZ:%x (%s:%d (%s))>", &SectionObject->FileObject->FileName, RelativeAddress, LineInfo.FileName, LineInfo.LineNumber, LineInfo.FunctionName); if (Context && LineInfo.NumParams) { int i; char *comma = ""; DbgPrint("("); for (i = 0; i < LineInfo.NumParams; i++) { DbgPrint ("%s%s=%llx", comma, LineInfo.Parameters[i].ValueName, LineInfo.Parameters[i].Value); comma = ","; } DbgPrint(")"); } return TRUE; } } #endif } end: DbgPrint("<%wZ:%x>", &LdrEntry->BaseDllName, RelativeAddress); return TRUE; }