📄 ecostest.cpp
字号:
nLength+=n; } else if (n<0) { break; } } TRACE(_T("End suck\n"));//sdf return nLength>0;}#endifvoid CeCosTest::LogTimeStampedOutput(LPCTSTR psz){ LogString(psz); /* String str(psz); // Timestamp the output at each _TCHAR('\n') int nLen=m_strOutput.GetLength(); TCHAR cPrev=(0==nLen?_TCHAR('\0'):((LPCTSTR )m_strOutput)[nLen-1]); TCHAR *c=str.GetBuffer(); LPCTSTR d=c; while(*c){ if(_TCHAR('\n')==cPrev){ TCHAR cSav=*c; *c=_TCHAR('\0'); LogString(d); Duration &dTime=m_bDownloading?m_nDownloadTime:m_nMaxInactiveTime; dTime=MAX(dTime,GdbTime()-m_tBase); String strTime; strTime.Format(_T("<") WFS _T("/") WFS _T(">\t"),WF(GdbTime()-m_tBase0), WF(GdbTime()-m_tBase)); //strTime.Format(_T("<%03d.%d> "),t/1000,(t%1000)/100); LogString(strTime); *c=cSav; d=c; } cPrev=*c; c++; } LogString(d); str.ReleaseBuffer(); */}#ifdef _WIN32BOOL WINAPI HandlerRoutine( DWORD dwCtrlType // control signal type ){ dwCtrlType; // eliminate compiler warning return TRUE;}#endifbool CeCosTest::InteractiveGdb(const String &strHost,int nPort,TCHAR **argv){ bool rc=false; if(strHost.GetLength()>0){ m_strExecutionHostPort=CeCosTestSocket::HostPort(strHost,nPort); Log(_T("Waiting to connect to %s...\n"),(LPCTSTR )m_strExecutionHostPort); } else { Log(_T("Waiting to connect to a server...\n")); } ConnectForExecution(); Log(_T("Connected to %s - waiting for target reset\n"),(LPCTSTR )m_strExecutionHostPort); String strHostPort,strOutput; // We read: // target ready indicator // any output so far // (if target ready) host:port if(GetTargetReady(strHostPort)){ Log(_T("Use %s\n"),(LPCTSTR)strHostPort); const TargetInfo &t=Target(Target()); String strGdb(t.Prefix()); strGdb+=_T("-gdb");#ifdef _WIN32 SetConsoleCtrlHandler(HandlerRoutine,TRUE); int n=_tspawnvp(_P_WAIT,strGdb,argv); if(-1==n){ Log(_T("Failed to spawn %s\n"),(LPCTSTR)strGdb); } else { rc=(0==n); } SetConsoleCtrlHandler(HandlerRoutine,FALSE);#else // UNIX int pid=fork(); switch(pid){ case -1: _ftprintf(stderr,_T("fork failed\n")); pid=0; break; case 0: // Process is created (we're the child) execvp(strGdb,argv); Log(_T("Error invoking %s - %s\n"),(LPCTSTR)strGdb,strerror(errno)); exit(1); break; default: // Process is created (we're the parent) { signal(SIGINT,SIG_IGN); int stat; waitpid(pid,&stat,0); rc=(0==stat); signal(SIGINT,SIG_DFL); } break; }#endif Log(_T("Gdb terminated\n")); // Tell the server we're through m_pSock->sendInteger(123,_T("Terminating ack")); } return rc;}void CALLBACK CeCosTest::ResetLogFunc(void *pParam, LPCTSTR psz) { CeCosTest *pTest=(CeCosTest *)pParam; TRACE(_T("Send Target Ready indicator=2\n")); pTest->m_pSock->sendInteger(2,_T("target ready indicator")); TRACE(_T("Send %s\n"),psz); pTest->m_pSock->sendString(psz,_T("output so far"));}CResetAttributes::ResetResult CeCosTest::Reset(bool bSendStatus){ return m_pPort->Reset(bSendStatus?ResetLogFunc:0,this);}CeCosTest::ExecutionParameters::RequestType CeCosTest::ExecutionParameters::RequestTypeValue(LPCTSTR psz){ int r; for(r=0;r<RequestTypeMax;r++){ if(0==_tcsicmp(psz,arRequestImage[r])){ break; } } return (RequestType)r;}#ifdef _WIN32void CeCosTest::RunGdb(LPCTSTR pszCmdline,LPCTSTR pszPrompt,const StringArray &arstrGdbCmds){ SetPath(m_strPath); CSubprocess sp; unsigned int idProcess=sp.Run(GetCurrentThreadId(),pszCmdline); if(!idProcess){ Log(_T("Failed to create gdb process: cmdline='%s'\n"),pszCmdline); TCHAR *pszMsg; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, sp.GetExitCode(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&pszMsg, 0, NULL ); // Display the string. Log(_T("%s\n"),pszMsg); // Free the buffer. LocalFree(pszMsg); } else { unsigned int nCmdIndex=0; SetStatus(NotStarted); m_nMaxInactiveTime=0; m_nTotalTime=0; m_nDownloadTime=0; m_bDownloading=true; m_tBase=GdbTime(); m_tBase0=GdbTime(); m_tWallClock0=Now(); TRACE(_T("RunGDb()\n")); int nLastGdbInst=0; while(Cancelled!=Status() && CheckForTimeout()){ MSG msg; if(::PeekMessage(&msg,NULL,WM_SUBPROCESS,WM_SUBPROCESS+1,PM_NOREMOVE)){ switch(::GetMessage(&msg,NULL,WM_SUBPROCESS,WM_SUBPROCESS+1)){ case 0: //WM_QUIT case -1: // error goto Done; case 1: if(WM_SUBPROCESS==msg.message && msg.wParam==idProcess){ if(msg.lParam){ LPTSTR pszMsg=(LPTSTR)msg.lParam; LogTimeStampedOutput(pszMsg); if(m_strOutput.GetLength()>20000){ LogString(_T("\n>>>> Infra FAIL\n*** too much output ***\n>>>>\n")); SetStatus(Fail); goto Done; } // Test for program loaded and started: // (remember SetStatus cannot downgrade the status if already > NoResult) if(OutputContains(_T("Starting program: /")) || (OutputContains(_T("Start address"))&&OutputContains(_T("Continuing.")))){ SetStatus(NoResult); } m_tBase=GdbTime(); // // If can only hit a single breakpoint don't expect cyg_test_exit to stop us: // if(!BreakpointsOperational() && (OutputContains(_T("EXIT:"))||OutputContains(_T("NOTAPPLICABLE:")))){ // goto Done; // } if(AtPrompt(pszPrompt)){ m_tBase=GdbTime(); TRACE(_T("RunGDb(1)\n")); // gdb's output included one or more prompts // Send another command along if(nCmdIndex>=arstrGdbCmds.size()){ // Nothing further to say to gdb - exit TRACE(_T("RunGDb(2)\n")); goto Done; // case 3 } else { String strCmd(arstrGdbCmds[nCmdIndex++]); TRACE(_T("RunGDb(2a) - strCmd='%s' nLastGdbInst=%d\n"),(LPCTSTR)strCmd,nLastGdbInst); // If at a prompt and we can see a GDB instruction, send it down LPCTSTR pszGdbcmd=_tcsstr(nLastGdbInst+(LPCTSTR)m_strOutput,_T("GDB:")); if(pszGdbcmd){ TRACE(_T("RunGDb(2b)\n")); pszGdbcmd+=4; TCHAR cTerm; if(_TCHAR('<')==*pszGdbcmd){ cTerm=_TCHAR('>'); pszGdbcmd++; } else { cTerm=_TCHAR('\n'); } TRACE(_T("RunGDb(2c)\n")); LPCTSTR c=_tcschr(pszGdbcmd,cTerm); if(c){ TRACE(_T("RunGDb(2d)\n")); strCmd=String(pszGdbcmd,c-pszGdbcmd); nLastGdbInst=c+1-(LPCTSTR )m_strOutput; nCmdIndex--; // undo increment above } } strCmd+=_TCHAR('\n'); LogString(strCmd); TRACE(_T("RunGDb(3)\n")); sp.Send(strCmd); TRACE(_T("RunGDb(4)\n")); if(0==_tcscmp(strCmd,_T("run\n"))||0==_tcscmp(strCmd,_T("cont\n"))){ m_tBase=GdbTime(); m_bDownloading=false; } TRACE(_T("RunGDb(5)\n")); } } delete [] pszMsg; } else { goto Done; } } break; } } else { // no message Sleep (500l); // sleep 500ms before the next peek } } Done: // Could use CygKill here sp.Kill(); TRACE(_T("RunGDb - Done\n")); AnalyzeOutput(); m_nTotalTime=Duration(Now()-m_tWallClock0); } TRACE(_T("Exiting RunGdb()\n"));}bool CeCosTest::GdbProcessAlive(){ DWORD dwExitRc; GetExitCodeProcess((HANDLE)m_pGdbProcesshandle,&dwExitRc); return STILL_ACTIVE==dwExitRc;}Time CeCosTest::GdbCpuTime(){ HANDLE hProcess=(HANDLE)m_pGdbProcesshandle; __int64 ftCreation,ftExit,ftKernel,ftUser; if(NULL!=hProcess && GetProcessTimes (hProcess,(FILETIME *)&ftCreation,(FILETIME *)&ftExit,(FILETIME *)&ftKernel,(FILETIME *)&ftUser)){ return Time((int)((ftKernel+ftUser)/10000)); } else { return 0; }}void CeCosTest::GetPath(String &strPath){ int nSize=GetEnvironmentVariable(_T("PATH"), NULL, 0); if(nSize>0){ GetEnvironmentVariable(_T("PATH"), strPath.GetBuffer(nSize), nSize); strPath.ReleaseBuffer(); } else { strPath=_T(""); }}void CeCosTest::SetPath(const String &strPath){ SetEnvironmentVariable(_T("PATH"), strPath);}#else // UNIXvoid CeCosTest::RunGdb(LPCTSTR pszCmdline,LPCTSTR pszPrompt,const StringArray &arstrGdbCmds){ int pipe_ends_w[2]; if (pipe(pipe_ends_w) < 0 ) { Log(_T("Failed to create pipe_ends_w - %s\n"),strerror(errno)); } else { int pipe_ends_r[2]; if (pipe(pipe_ends_r) < 0 ) { Log(_T("Failed to create pipe_ends_r - %s\n"),strerror(errno)); } else { int new_pid; ENTERCRITICAL; // Ensure no one else has the lock such that the child might block in future new_pid = fork(); // This leave is executed in *both* the child and parent LEAVECRITICAL; switch (new_pid) { // Fork failed case -1: Log(_T("Failed to create gdb process - %s\n"),strerror(errno)); break; case 0: // Process is created (we're the child) // No point in calling Log in this process // Input to child process if (dup2(pipe_ends_w[0], 0) < 0) { TRACE(_T("dup2 error\n")); exit(1); } // Output from process if (dup2(pipe_ends_r[1], 2) < 0) { TRACE(_T("dup2 error\n")); exit(2); } if (dup2(pipe_ends_r[1], 1) < 0) { TRACE(_T("dup2 error\n")); exit(3); } setvbuf(stdout,0,_IONBF,0); setvbuf(stderr,0,_IONBF,0); { StringArray ar; int argc=String(pszCmdline).Chop(ar,_TCHAR(' '),true); char **argv=new char *[1+argc]; int i; for(i=0;i<argc;i++){ argv[i]=ar[i]; } argv[i]=0; execvp(argv[0], argv); delete [] argv; } TRACE(_T("exec error - %s\n"),strerror(errno)); exit(4); default: // Process is created (we're the parent) TRACE(_T("Forked to create gdb process %s - pid is <%d>\n"), pszCmdline, new_pid); if (fcntl(pipe_ends_r[0], F_SETFL, O_NONBLOCK) <0) { Log(_T("Couldn't set pipe non-blocking - %s\n"),strerror(errno)); } else { m_pGdbProcesshandle=(void *)new_pid; VTRACE(_T("RunGdb():Calling DriveGdb\n")); m_rPipeHandle=(void *)pipe_ends_r[0]; m_wPipeHandle=(void *)pipe_ends_w[1]; DriveGdb (pszPrompt,arstrGdbCmds); // Finished one way or another. Kill gdb now TRACE(_T("Finished processing this test.\n")); if(GdbProcessAlive()){ TRACE(_T("Killing gdb\n")); // We need to kill gdb *and* its children FILE *f=popen(_T("ps -l"),_T("r")); if(f){ TCHAR buf[100]; while(_fgetts(buf,sizeof(buf)-1,f)){ int F,UID,PID,PPID,C,PRI,NI,SZ,HH,MM,SS; TCHAR discard[100]; // Output is in the form
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -