/* ** Take a string which is supposed to be an executable address, ** and find out what that address is. */ ULONG FindExecAddr(char *label, char **brkDesc) { ULONG addr = 0; char *desc; char *dummy; ULONG lineNum; DebugModule *module; char funcName[MAX_FUNCNAME]; char sourceName[CCHMAXPATH]; /* ** If there is no label, give up the ghost! */ if(label == NULL) return 0; /* ** Find the address of the line given a line number. */ if(label[0] == '.') { module = FindModule(debugBuffer.MTE, NULL); FindSource(module, Linearize(debugBuffer.EIP, debugBuffer.CS), funcName, sourceName, &lineNum); /* Cannot find source module. */ if(strcmp(sourceName, "UNKNOWN") == 0) { return 0; } lineNum = strtol(&label[1], &dummy, 0); addr = FindSourceLine(module, lineNum, sourceName); /* ** Build a string which describes the breakpoint. */ desc = malloc(strlen(label) + strlen(sourceName) + 1); strcpy(desc, sourceName); strcat(desc, ":"); strcat(desc, &label[1]); *brkDesc = desc; return addr; } /* ** If we have a '!' in the string, then it is a compound ** filename/line number */ if(strchr(label, '!') != NULL) { char *line; line = strchr(label, '!'); *line = '\0'; module = FindModule(debugBuffer.MTE, NULL); FindSource(module, Linearize(debugBuffer.EIP, debugBuffer.CS), funcName, sourceName, &lineNum); /* Cannot find source module. */ if(strcmp(sourceName, "UNKNOWN") == 0) { return 0; } lineNum = strtol(&label[1], &dummy, 0); addr = FindSourceLine(module, lineNum, sourceName); /* ** Build a string which describes the breakpoint. */ desc = malloc(strlen(label) + strlen(sourceName) + 1); strcpy(desc, sourceName); strcat(desc, ":"); strcat(desc, &label[1]); *brkDesc = desc; return addr; } /* ** Try finding the name as a function */ if((addr = FindFuncAddr(NULL, label)) != 0) { desc = malloc(strlen(label) + 1); strcpy(desc, label); *brkDesc = desc; return addr; } /* ** If we could not find a function, try using the label as ** a hex offset to break at. */ addr = StrToAddr(label, TOADDR_CODE); desc = malloc(strlen(label) + 1); strcpy(desc, label); *brkDesc = desc; return addr; }
/* ** Do a single step to the next source instruction. */ int CommandStep(char **ptrs) { int i; ULONG addr; ULONG lineNum; Breakpoint *bp; DebugModule *module; char funcName[MAX_FUNCNAME]; char funcName2[MAX_FUNCNAME]; char sourceName[CCHMAXPATH]; /* ** Provide a reference to keep from getting a compile warning. */ ptrs; /* ** Find the address specified. */ module = FindModule(debugBuffer.MTE, NULL); FindSource(module, Linearize(debugBuffer.EIP, debugBuffer.CS), funcName, sourceName, &lineNum); for(i=0; i<100; i++) { lineNum++; addr = FindSourceLine(module, lineNum, sourceName); if(addr != 0) { FindSource(module, addr, funcName2, sourceName, &lineNum); if(strcmp(funcName2, funcName) == 0) break; fprintf(logFile, "Unable to find next line. Next function found!\n"); return -1; } } /* ** Did we find a line */ if(addr == 0) { fprintf(logFile, "Unable to find next line.\n"); return -1; } /* ** Set the breakpoint at the address specified. */ debugBuffer.Addr = addr; debugBuffer.Len = 1; debugBuffer.Index = 0; debugBuffer.Value = DBG_W_Local | DBG_W_Execute; DispatchCommand(DBG_C_SetWatch); /* ** Add the breakpoint to the list, and tag it as a 'go' ** breakpoint which will unconditionally be cleared the ** next time we get back from the debuggee. */ if(Breakpoints) { for(i=0, bp=Breakpoints; bp->next; i++, bp=bp->next) ; bp->next = malloc(sizeof(Breakpoint)); bp = bp->next; } else { i = 0; Breakpoints = bp = malloc(sizeof(Breakpoint)); } bp->id = debugBuffer.Index; bp->addr = addr; bp->next = NULL; bp->desc = NULL; bp->oneTimeFlag = 1; return DBG_C_Go; }
/* ** Display the source file and line number. */ int DisplaySource(DebugModule *module, char *sourceName, int lineNum) { int i, lastChar, is32Bit; int curLine; FILE *file = NULL; View *viewData = (View *) module->ViewData; ULONG addr, addr2; char buff[CCHMAXPATH]; char dummy[CCHMAXPATH]; /* ** Find out whether this is a 32 bit segment. */ DispatchCommand(DBG_C_ReadReg); is32Bit = (debugBuffer.CSAtr & 0x80) != 0; /* ** If the view data does not exist, create and initialize it. */ if(viewData == NULL) { viewData = module->ViewData = calloc(sizeof(View), 1); viewData->lastSource = strdup(""); viewData->basePath = strdup(""); } /* ** Find and open the source file. */ if(strlen(sourceName) > 0) { strcpy(buff, sourceName); _splitpath(sourceName, drive, dir, fname, ext); _splitpath(viewData->basePath, drive, dir, dummy, dummy); _makepath(buff, drive, dir, fname, ext); while((file = fopen(buff, "r")) == NULL) { #ifdef SHERLOCK buff[0] = 0; #else fprintf(logFile, "Please enter path for %s\n", sourceName); fgets(buff, sizeof(buff), stdin); #endif while((strlen(buff) > 0) && isspace(*buff)) buff[strlen(buff) - 1] = 0; if(strlen(buff) == 0) return 0; lastChar = strlen(buff) - 1; while(isspace(buff[lastChar])) { buff[lastChar] = 0; lastChar--; } if((buff[lastChar] != '\\') && (buff[lastChar] != '/')) strcat(buff, "/"); _splitpath(buff, drive, dir, dummy, dummy); _makepath(buff, drive, dir, fname, ext); } } /* ** Free/show the last source viewed. */ if(viewData->lastSource) free(viewData->lastSource); viewData->lastSource = strdup(buff); /* ** Free the previous path spec. */ if(viewData->basePath) free(viewData->basePath); _splitpath(buff, drive, dir, fname, ext); _makepath(buff, drive, dir, "", ""); viewData->basePath = strdup(buff); /* ** Go to just before the line specific. */ if(file) { curLine = 0; for(curLine=1; curLine < lineNum - 5; curLine++) { fgets(buff, sizeof(buff), file); } } /* ** Now, display the source. */ if(file) { for(i=0; i<10; i++, curLine++) { if(file) if(fgets(buff, sizeof(buff), file) == NULL) break; if(ShouldDumpSource) { if(curLine == lineNum) fprintf(logFile, "*%5d: %s", curLine, buff); else fprintf(logFile, " %5d: %s", curLine, buff); } if((addr = FindSourceLine(module, curLine, sourceName)) != 0) { int j; /* ** Find the next line. */ for(j=1; j < 10; j++) { if((addr2=FindSourceLine(module,curLine+j,sourceName))!=0) break; } } if(addr2 == 0) addr2 = addr + 0x10; if(ShouldDumpAsm) DumpAsm(addr, addr2-addr, is32Bit); } } else { addr = Linearize(debugBuffer.EIP, debugBuffer.CS); DumpAsm(addr, 0x20, is32Bit); addr2 = addr + 0x20; } viewData->lastLine = curLine - 1; viewData->lastAddr = addr2; if(file) fclose(file); return 1; }
/* ** View the assembler for the address/line specified. */ int CommandUnassemble(char **ptrs) { DebugModule *module; View *viewData; char *srcEnd; ULONG addr; int lineNum; int is32Bit; char sourceName[CCHMAXPATH]; /* ** Get the common data. */ module = FindModule(debugBuffer.MTE, NULL); viewData = (View *) module->ViewData; if(viewData == NULL) { viewData = module->ViewData = calloc(sizeof(View), 1); viewData->lastSource = strdup(""); viewData->basePath = strdup(""); } is32Bit = (debugBuffer.CSAtr & 0x80) != 0; addr = Linearize(debugBuffer.EIP, debugBuffer.CS); /* ** View the next lines to be displayed. */ if(ptrs[2] == NULL) { DumpAsm(viewData->lastAddr, 0x20, is32Bit); viewData->lastAddr = addr + 0x20; return -1; } /* ** View a source line. */ if(ptrs[2][0] == '.') { /* ** Find the line number or the file name/line number */ if(isdigit(ptrs[2][1])) { lineNum = atol(&ptrs[2][1]); if(viewData->lastSource == NULL) { fprintf(logFile, "No source yet displayed\n"); return -1; } strcpy(sourceName, viewData->lastSource); } else { strcpy(sourceName, &ptrs[2][1]); *strrchr(sourceName, ':') = 0; lineNum = atol(strrchr(ptrs[2], ':') + 1); } addr = FindSourceLine(module, lineNum, sourceName); DumpAsm(addr, 0x20, is32Bit); viewData->lastAddr = addr + 0x20; return -1; } /* ** Get a view at a given offset. */ if(isxdigit(ptrs[2][0])) { addr = StrToAddr(ptrs[2], TOADDR_CODE); DumpAsm(addr, 0x20, is32Bit); viewData->lastAddr = addr + 0x20; return -1; } /* ** ERROR! */ fprintf(logFile, "Invalid syntax\n"); return -1; }
void CDebugMgr::RecordException(PEXCEPTION_POINTERS pExceptionInfo) { PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord; // First print information about the type of fault m_pchBuffer += wsprintf(m_pchBuffer, "Exception code: %08X\n", pExceptionRecord->ExceptionCode); // Now print information about where the fault occured TCHAR szFaultingModule[MAX_PATH]; DWORD section, offset; FindLogicalAddress( pExceptionRecord->ExceptionAddress, szFaultingModule, sizeof( szFaultingModule ), section, offset ); m_pchBuffer += wsprintf(m_pchBuffer,"Fault address: %08X %02X:%08X %s", pExceptionRecord->ExceptionAddress, section, offset, szFaultingModule ); TCHAR szMap[MAX_PATH] = ""; wsprintf(szMap, szFaultingModule); wsprintf(&szMap[lstrlen(szMap)-3], "MAP"); TCHAR szSymbol[256] = "<unknown>"; TCHAR szUnmangledSymbol[1024] = "<unknown>"; TCHAR szObject[128] = "<unknown>"; if ( m_dwOptions & DEBUGMGR_RESOLVESYMBOLS ) { if ( FindSymbol(szMap, section, offset, szSymbol, szObject) ) { if ( m_dwOptions & DEBUGMGR_UNMANGLESYMBOLS && *szSymbol == '?' ) { UnDecorateSymbolName(szSymbol, szUnmangledSymbol, 1024, UNDNAME_COMPLETE); } else { wsprintf(szUnmangledSymbol, szSymbol); } m_pchBuffer += wsprintf(m_pchBuffer, " in function %s in object file %s", szUnmangledSymbol, szObject); if ( m_dwOptions & DEBUGMGR_RESOLVESOURCELINE ) { TCHAR szSource[256]; TCHAR szLine[256]; if ( FindSourceLine(szMap, szObject, section, offset, szSource, szLine) ) { m_pchBuffer += wsprintf(m_pchBuffer, " at Line %s of %s\n", szLine, szSource); } else { m_pchBuffer += wsprintf(m_pchBuffer, " at Line ??? of ???\n"); } } else { m_pchBuffer += wsprintf(m_pchBuffer, "\n\n"); } } else { m_pchBuffer += wsprintf(m_pchBuffer, "\n"); } } else { m_pchBuffer += wsprintf(m_pchBuffer, "\n"); } PCONTEXT pCtx = pExceptionInfo->ContextRecord; // Show the registers m_pchBuffer += wsprintf(m_pchBuffer, "EAX:%08X\nEBX:%08X\nECX:%08X\nEDX:%08X\nESI:%08X\nEDI:%08X\n", pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, pCtx->Esi, pCtx->Edi ); m_pchBuffer += wsprintf(m_pchBuffer,"CS:EIP:%04X:%08X\n", pCtx->SegCs, pCtx->Eip ); m_pchBuffer += wsprintf(m_pchBuffer,"SS:ESP:%04X:%08X EBP:%08X\n", pCtx->SegSs, pCtx->Esp, pCtx->Ebp ); m_pchBuffer += wsprintf(m_pchBuffer,"DS:%04X ES:%04X FS:%04X GS:%04X\n", pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs ); m_pchBuffer += wsprintf(m_pchBuffer,"Flags:%08X\n", pCtx->EFlags ); }
void CDebugMgr::RecordStack(const CONTEXT* pContext) { m_pchBuffer += wsprintf(m_pchBuffer,"\nCall stack:\n" ); m_pchBuffer += wsprintf(m_pchBuffer,"Address Frame Logical addr Module\n" ); DWORD pc = pContext->Eip; PDWORD pFrame, pPrevFrame; pFrame = (PDWORD)pContext->Ebp; do { TCHAR szModule[MAX_PATH] = ""; DWORD section = 0, offset = 0; FindLogicalAddress((PVOID)pc, szModule,sizeof(szModule),section,offset ); m_pchBuffer += wsprintf(m_pchBuffer,"%08X %08X %04X:%08X %s", pc, pFrame, section, offset, szModule ); // See if we need to spit out symbol/source/line info if ( m_dwOptions & DEBUGMGR_RESOLVESYMBOLS ) { // Generate the name of the map file TCHAR szMap[MAX_PATH] = ""; wsprintf(szMap, szModule); wsprintf(&szMap[lstrlen(szMap)-3], "MAP"); TCHAR szSymbol[256] = "<unknown>"; TCHAR szUnmangledSymbol[1024] = "<unknown>"; TCHAR szObject[128] = "<unknown>"; if ( FindSymbol(szMap, section, offset, szSymbol, szObject) ) { if ( m_dwOptions & DEBUGMGR_UNMANGLESYMBOLS && *szSymbol == '?' ) { UnDecorateSymbolName(szSymbol, szUnmangledSymbol, 1024, UNDNAME_COMPLETE); } else { wsprintf(szUnmangledSymbol, szSymbol); } } m_pchBuffer += wsprintf(m_pchBuffer, " in function %s in object file %s", szUnmangledSymbol, szObject); if ( m_dwOptions & DEBUGMGR_RESOLVESOURCELINE ) { TCHAR szSource[256]; TCHAR szLine[256]; if ( FindSourceLine(szMap, szObject, section, offset, szSource, szLine) ) { m_pchBuffer += wsprintf(m_pchBuffer, " at Line %s of %s\n", szLine, szSource); } else { m_pchBuffer += wsprintf(m_pchBuffer, " at Line ??? of ???\n"); } } else { m_pchBuffer += wsprintf(m_pchBuffer, "\n\n"); } } else { m_pchBuffer += wsprintf(m_pchBuffer, "\n"); } // Go on to the next stack frame pc = pFrame[1]; pPrevFrame = pFrame; pFrame = (PDWORD)pFrame[0]; // proceed to next higher frame on stack if ( (DWORD)pFrame & 3 ) // Frame pointer must be aligned on a break; // DWORD boundary. Bail if not so. if ( pFrame <= pPrevFrame ) break; // Can two DWORDs be read from the supposed frame address? if ( IsBadWritePtr(pFrame, sizeof(PVOID)*2) ) break; } while ( 1 ); }