📄 ecostest.cpp
字号:
Log(_T("Resetting target using %s"),(LPCTSTR)m_pPort->ResetString()); bTargetReady=(CResetAttributes::RESET_OK==Reset(true)); } TRACE(_T("Send Target Ready indicator=%d\n"),bTargetReady); m_pSock->sendInteger(bTargetReady,_T("target ready indicator")); int nAck; int dTimeout=m_ep.DownloadTimeout()+MAX(3*m_ep.ActiveTimeout(),15*60*1000); if(bTargetReady){ if(CeCosTestSocket::IsLegalHostPort(m_pPort->Serial())){ TRACE(_T("Sending %s\n"),(LPCTSTR )m_pPort->Serial()); m_pSock->sendString(m_pPort->Serial(),_T("Serial name")); m_pSock->recvInteger(nAck,_T("Terminating ack"),dTimeout); TRACE(_T("Terminating ack=%d\n"),nAck); } else { String strHostPort(CeCosTestSocket::HostPort(CeCosTestUtils::HostName(),nAuxPort)); TRACE(_T("Using %s\n"),(LPCTSTR )strHostPort); if(m_pSock->sendString(strHostPort,_T("host:port"))){ // This Boolean signifies that the serial<-->tcp/ip conversation is done. It may be set // on completion of the ConnectSocketToSerial thread (which is why we pass it to runthread) // and also set by us to *cause* the thread to complete. bool bConnectSocketToSerialThreadDone=false; // Indication of termination of ConnectSocketToSerial thread m_bStopConnectSocketToSerial=false; // Used to tap ConnectSocketToSerial thread on the shoulder CeCosThreadUtils::RunThread(SConnectSocketToSerialThreadFunc,this,&bConnectSocketToSerialThreadDone,_T("SConnectSocketToSerialThreadFunc")); // Wait for either client or the ConnectSocketToSerial thread to finish. m_pSock->recv(&nAck,1,_T("Terminating ack"),dTimeout,DerefBool,&bConnectSocketToSerialThreadDone); TRACE(_T("Terminating ack=%d\n"),nAck); if(!bConnectSocketToSerialThreadDone){ // Tap ConnectSocketToSerial thread on the shoulder TRACE(_T("Waiting for ConnectSocketToSerial thread to terminate...\n")); m_bStopConnectSocketToSerial=true; CeCosThreadUtils::WaitFor(bConnectSocketToSerialThreadDone); } TRACE(_T("ConnectSocketToSerial thread terminated...\n")); } } } } delete this;}bool CeCosTest::send(const void *pData,unsigned int nLength,LPCTSTR pszMsg,Duration dTimeout){ return m_pSock->send(pData,nLength,pszMsg,dTimeout,IsCancelled,this);}bool CeCosTest::recv(const void *pData,unsigned int nLength,LPCTSTR pszMsg,Duration dTimeout){ return m_pSock->recv(pData,nLength,pszMsg,dTimeout,IsCancelled,this);}void CeCosTest::Log(LPCTSTR pszFormat, ...){ va_list args; va_start(args, pszFormat); String str; str.vFormat(pszFormat,args); va_end(args); LogString(str);}void CeCosTest::LogString(LPCTSTR psz){ if(*psz){ ENTERCRITICAL; m_strOutput+=psz; LEAVECRITICAL; if(CeCosTrace::IsInteractive()){ CeCosTrace::Out(psz); } else { TRACE(_T("%s"),psz); } }}bool CeCosTest::sendResult(Duration dTimeout){ bool rc= m_pSock->sendInteger(m_Status,_T("result"),dTimeout) && m_pSock->sendInteger(m_nDownloadTime,_T("result"),dTimeout) && m_pSock->sendInteger(m_nTotalTime,_T("result"),dTimeout) && m_pSock->sendInteger(m_nMaxInactiveTime,_T("result"),dTimeout) && m_pSock->sendString (m_strOutput,_T("result"),dTimeout); return rc;}bool CeCosTest::recvResult(Duration dTimeout){ String strOutput; int nStatus=StatusTypeMax; bool rc= m_pSock->recvInteger(nStatus,_T("result"),dTimeout) && m_pSock->recvInteger(m_nDownloadTime,_T("result"),dTimeout) && m_pSock->recvInteger(m_nTotalTime,_T("result"),dTimeout) && m_pSock->recvInteger(m_nMaxInactiveTime,_T("result"),dTimeout) && m_pSock->recvString (strOutput,_T("result"),dTimeout); m_Status=(StatusType)MIN(nStatus,StatusTypeMax); LogString(strOutput); return rc;}#ifndef _WIN32// This function may be run as a thread (win32) or called (unix).// It runs gdb.void CeCosTest::DriveGdb(LPCTSTR pszPrompt,const StringArray &arstrGdbCmds){ 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("DriveGdb()\n")); int nLastGdbInst=0; // Loop until 1 of: // 1. Timeout detected // 2. Gdb process is dead // 3. At a gdb prompt and no more commands to send to gdb // 4. Pipe read failure // 5. Pipe write failure do { String str; int readrc=ReadPipe(str,/*bBlockingReads=*/false); switch(readrc){ case 0: Sleep(250); // only unix will execute this break; case -1: goto Done; // case 4 break; default: LogTimeStampedOutput(str); 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("DriveGdb(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("DriveGdb(2)\n")); goto Done; // case 3 } else { String strCmd(arstrGdbCmds[nCmdIndex++]); TRACE(_T("DriveGdb(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("DriveGdb(2b)\n")); pszGdbcmd+=4; TCHAR cTerm; if(_TCHAR('<')==*pszGdbcmd){ cTerm=_TCHAR('>'); pszGdbcmd++; } else { cTerm=_TCHAR('\n'); } TRACE(_T("DriveGdb(2c)\n")); LPCTSTR c=_tcschr(pszGdbcmd,cTerm); if(c){ TRACE(_T("DriveGdb(2d)\n")); strCmd=String(pszGdbcmd,c-pszGdbcmd); nLastGdbInst=c+1-(LPCTSTR)m_strOutput; nCmdIndex--; // undo increment above } } strCmd+=_TCHAR('\n'); LogString(strCmd); TRACE(_T("DriveGdb(3)\n")); if(!WritePipe(strCmd)){ TRACE(_T("Writepipe returned error\n")); goto Done; // case 5 } TRACE(_T("DriveGdb(4)\n")); if(0==_tcscmp(strCmd,_T("run\n"))||0==_tcscmp(strCmd,_T("cont\n"))){ m_tBase=GdbTime(); m_bDownloading=false; } TRACE(_T("DriveGdb(5)\n")); } } break; } } while (GdbProcessAlive() && CheckForTimeout()); // cases 2 and 1 Done: TRACE(_T("DriveGdb() - done\n")); Suck(pszPrompt); if(GdbProcessAlive() && AtPrompt(pszPrompt)){ LogString(_T("bt\n")); WritePipe(_T("bt\n")); Suck(pszPrompt); LogString(_T("quit\n")); WritePipe(_T("quit\n")); } // Read anything gdb has to say [within limits] Suck(pszPrompt); AnalyzeOutput(); m_nTotalTime=Now()-m_tWallClock0; TRACE(_T("Exiting DriveGdb()\n")); }#endif// Return time used by inferior gdb process - CPU for sim, wallclock otherwiseTime CeCosTest::GdbTime(){ return _TCHAR('\0')==*(m_pPort->Serial())?GdbCpuTime():Now();}bool CeCosTest::CheckForTimeout(){ bool rc=false; if(TimeOut!=m_Status && DownloadTimeOut!=m_Status){ Duration &dTime=m_bDownloading?m_nDownloadTime:m_nMaxInactiveTime; Time t=GdbTime(); if(t){ dTime=MAX(dTime,Duration(GdbTime()-m_tBase)); } Duration dTimeout=m_bDownloading?DownloadTimeout():ActiveTimeout(); if(dTimeout!=NOTIMEOUT && dTime>dTimeout) { Log(_T("\n*** Timeout - %s time ") WFS _T(" exceeds limit of ") WFS _T("\n"), m_bDownloading?_T("download"):_T("MAX inactive"),WF(dTime),WF(dTimeout)); SetStatus(m_bDownloading?DownloadTimeOut:TimeOut); } else if(Now()-m_tWallClock0>MAX(3*dTimeout,15*60*1000)){ Log(_T("\n*** Timeout - total time ") WFS _T(" exceeds limit of ") WFS _T("\n"), WF(Now()-m_tWallClock0),WF(MAX(3*dTimeout,15*60*1000))); SetStatus(m_bDownloading?DownloadTimeOut:TimeOut); } else { rc=true; } } return rc;}void CeCosTest::Interactive(LPCTSTR pszFormat, ...){ va_list marker; va_start (marker, pszFormat); String str; str.vFormat(pszFormat,marker); va_end (marker); if(CeCosTrace::IsInteractive()){ CeCosTrace::Out(str); } else { CeCosTrace::Trace(_T("%s"),(LPCTSTR)str); }}LPCTSTR const CeCosTest::Title() const { return m_strTitle;}// Convert a path to something a cygwin tool will understand. Used when invoking -size and -gdbString CeCosTest::CygPath (LPCTSTR pszPath){#ifdef _WIN32 String str; TCHAR *buf=str.GetBuffer(2+MAX_PATH); TCHAR *pszFname; if(::GetFullPathName(pszPath,MAX_PATH,1+buf, &pszFname)){ GetShortPathName(1+buf,1+buf,MAX_PATH); // ignore errors buf[0]=_TCHAR('/'); buf[2]=buf[1]; buf[1]=_TCHAR('/'); for(int i=3;buf[i];i++){ if(_TCHAR('\\')==buf[i]){ buf[i]=_TCHAR('/'); } } str.ReleaseBuffer(); return str; } else { str.ReleaseBuffer(); return pszPath; }#endif return pszPath;}void CeCosTest::SetExecutable(LPCTSTR pszExecutable){ m_strOutput=_T(""); m_strResultString=_T(""); m_strExecutable=pszExecutable; if(pszExecutable && !GetSizes(m_strExecutable, m_ep.Target(), m_nFileSize, m_nStrippedSize)){ const TargetInfo &t=Target(Target()); Log(_T("Failed to run %s-size to determine executable size of %s\n"),t.Prefix(),pszExecutable); }}// Calculate the sizes of the given file. The target parameter is necessary in order to // determine which -size executable to use to do the job.bool CeCosTest::GetSizes(LPCTSTR pszExecutable, LPCTSTR target,unsigned int &nFileSize, unsigned int &nStrippedSize){ bool rc=false; nStrippedSize=nFileSize=0; struct _stat buf; const TargetInfo &t=Target(target); LPCTSTR pszPrefix=t.Prefix(); if(0==_tstat(pszExecutable,&buf) && _TCHAR('\0')!=*pszPrefix){ // File at least exists... nFileSize=buf.st_size; String strSize(pszPrefix); strSize+=_T("-size "); strSize+=CygPath(pszExecutable); const TCHAR *c=0;#ifdef _WIN32 CSubprocess sp; String strOut; if(!sp.Run(strOut,strSize,NULL)){ return true; } c=_tcschr(strOut,_TCHAR('\n')); if(c){ c++; }#else // UNIX TCHAR buf[256]; FILE *f=POPEN(strSize,_T("r")); if(f){ _fgetts(buf,sizeof buf-1,f); _fgetts(buf,sizeof buf-1,f); PCLOSE(f); c=buf; }#endif int s1=0; int s2=0; rc=(c && 2==_stscanf(c,_T(" %d %d"),&s1,&s2)); nStrippedSize=s1+s2; } return rc;}void CeCosTest::SetTimeouts (Duration dActive,Duration dElapsed){ m_ep.SetActiveTimeout (dActive); m_ep.SetDownloadTimeout(dElapsed);}void CeCosTest::CloseSocket (){ delete m_pSock; m_pSock=0;}bool CeCosTest::AtPrompt(LPCTSTR pszPrompt){ unsigned int nPromptLen=_tcslen(pszPrompt); return m_strOutput.GetLength()>=nPromptLen && 0==_tcscmp((LPCTSTR )m_strOutput+m_strOutput.GetLength()-nPromptLen,pszPrompt);}#ifndef _WIN32bool CeCosTest::Suck(LPCTSTR pszPrompt,Duration d){ TRACE(_T("Suck handle=%08x\n"),m_rPipeHandle);//sdf // Read until: // 8k read // timeout elapsed // gdb prompt reached // pipe error Time t0=Now(); int nLength=0; while(nLength<8192 && m_rPipeHandle && !AtPrompt(pszPrompt) && Now()-t0<d){ String str; int n=ReadPipe(str); if(n>0){ LogTimeStampedOutput(str);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -