📄 ecostest.cpp
字号:
Log(_T("Could not create %s - %s\n"),(LPCTSTR)m_strExecutable,strerror(errno)); bCanRun=false; } unsigned int nBufSize=MIN(100000,m_nFileSize); Buffer b(nBufSize); unsigned int nWritten=0; unsigned int nRead=0; while(nRead<m_nFileSize){ int nToRead=MIN(nBufSize,m_nFileSize-nRead); if(!recv( b.Data(), nToRead, _T("executable"))){ break; } nRead+=nToRead; if(0!=f2){ char *c=(char *)b.Data(); while(nToRead>0){ int w=fwrite(c,1,nToRead,f2); if(-1==w){ Log(_T("Write error on %s - %s\n"),(LPCTSTR)m_strExecutable,strerror(errno)); bCanRun=false; break; } nWritten+=w; c+=w; nToRead-=w; } } } TRACE(_T("Accept - done reading [%d bytes read, %d bytes written]\n"),nRead,nWritten); if(0!=f2){ fclose(f2); _tchmod(m_strExecutable,00700); // user read, write and execute } if(0!=f2 && m_nFileSize!=nWritten){ Log(_T("Failed to create %s correctly [%d/%d bytes written]\n"),(LPCTSTR)m_strExecutable, nWritten, m_nFileSize); bCanRun=false; } SetExecutable(m_strExecutable); // to set stripped length and title RunLocal(); _tunlink(m_strExecutable); } sendResult(); m_pSock->recvInteger(n); // receive an ack } else { // Client-side GDB bool bTargetReady; if(_TCHAR('\0')==*(m_pResource->ResetString())){ bTargetReady=true; TRACE(_T("No reset possible\n")); } else { Log(_T("Resetting target using %s"),(LPCTSTR)m_pResource->ResetString()); bTargetReady=(CResetAttributes::RESET_OK==m_pResource->Reset(ResetLogFunc,this)); } TRACE(_T("Send Target Ready indicator=%d\n"),bTargetReady); m_pSock->sendInteger(bTargetReady,_T("target ready indicator")); int nAck=-1; if(bTargetReady){ if(CeCosSocket::IsLegalHostPort(m_pResource->Serial())){ TRACE(_T("Sending %s\n"),(LPCTSTR)m_pResource->Serial()); if(m_pSock->sendString(m_pResource->Serial(),_T("Serial name")) && m_pSock->recvInteger(nAck,_T("Terminating ack"),CeCosSocket::NOTIMEOUT)){ TRACE(_T("Terminating ack=%d\n"),nAck); } } else { String strHostPort(CeCosSocket::HostPort(CeCosSocket::MyHostName(),m_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. if(m_pSock->recv(&nAck,sizeof(int),_T("Terminating ack"),CeCosSocket::NOTIMEOUT,DerefBool,&bConnectSocketToSerialThreadDone)){ TRACE(_T("Session terminated by request of client (%s)\n"),(LPCTSTR)Image((StatusType)nAck)); } else if(0!=m_pSock->SocketError()){ TRACE(_T("Session terminated by socket error - %s\n"),(LPCTSTR)m_pSock->SocketErrString()); } if(!bConnectSocketToSerialThreadDone){ // Tap ConnectSocketToSerial thread on the shoulder TRACE(_T("Waiting for ConnectSocketToSerial thread to terminate...\n")); m_bStopConnectSocketToSerial=true; CeCosThreadUtils::WaitFor(bConnectSocketToSerialThreadDone); } } } } } 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;}// Return time used by inferior gdb process - CPU for sim, wallclock otherwiseTime CeCosTest::InferiorTime() const{ if(*(m_pResource->Serial())){ return Now(); } if(!m_psp){ return 0; } Time now=Now(); if(now-m_tPrevSample>1000){ m_tPrevSample=now; m_tInferiorCpuTime=m_psp->CpuTime(); } return m_tInferiorCpuTime;}bool CeCosTest::CheckForTimeout(){ bool rc=(Cancelled!=Status()); if(TimeOut!=m_Status && DownloadTimeOut!=m_Status){ Time t=InferiorTime(); if(t){ // We have been able to measure the time if(m_bDownloading){ m_nDownloadTime=MAX(m_nDownloadTime,Duration(InferiorTime()-m_tBase)); if(m_nDownloadTime>m_ep.DownloadTimeout()){ Log(_T("\n*** Timeout - download time ") WFS _T(" exceeds limit of ") WFS _T("\n"),WF(m_nDownloadTime),WF(m_ep.DownloadTimeout())); rc=false; } } else { m_nMaxInactiveTime=MAX(m_nMaxInactiveTime,Duration(InferiorTime()-m_tBase)); if (m_nMaxInactiveTime>m_ep.ActiveTimeout()) { Log(_T("\n*** Timeout - inactive time ") WFS _T(" exceeds limit of ") WFS _T("\n"),WF(m_nMaxInactiveTime),WF(m_ep.ActiveTimeout())); rc=false; } } } m_nTotalTime=Duration(Now()-m_tWallClock0);/* if(m_nTotalTime>m_ep.ElapsedTimeout()){ Log(_T("\n*** Timeout - total time ") WFS _T(" exceeds limit of ") WFS _T("\n"), WF(m_nTotalTime),WF(m_ep.ElapsedTimeout())); rc=false; }*/ if(!rc){ SetStatus(m_bDownloading?DownloadTimeOut:TimeOut); } } return rc;}// 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(""); if(pszExecutable){ m_strExecutable=pszExecutable; if(m_ep.Platform()){ GetSizes(); } else { ERROR(_T("Don't know how to get sizes of this platform type\n")); } } else { m_strExecutable=_T(""); }}// 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(){TRACE(_T("GetSizes %s\n"),(LPCTSTR)Executable()); bool rc=false; m_nStrippedSize=m_nFileSize=0; LPCTSTR pszPrefix=m_ep.Platform()->Prefix(); struct _stat buf; if(-1==_tstat(Executable(),&buf)){ Log(_T("%s does not exist\n"),(LPCTSTR)Executable()); } else if (_TCHAR('\0')==*pszPrefix){ LogString(_T("No prefix to run a size program\n")); } else { m_nFileSize=buf.st_size; const String strSizeCmd(String::SFormat(_T("%s-size %s"),pszPrefix,(LPCTSTR)CygPath(Executable()))); String strOut; CSubprocess sp; if(!sp.Run(strOut,strSizeCmd)){ Log(_T("Failed to run \"%s\" - %s\n"),(LPCTSTR)strSizeCmd,(LPCTSTR)sp.ErrorString()); } else { const TCHAR *c=_tcschr(strOut,_TCHAR('\n')); if(c){ c++; } int s1=0; int s2=0; if(c && 2==_stscanf(c,_T(" %d %d"),&s1,&s2)){ rc=true; m_nStrippedSize=s1+s2; } TRACE(_T("GetSizes %s rc=%d file size=%d stripped size=%d\n"),(LPCTSTR)Executable(),rc,m_nFileSize,m_nStrippedSize); } } return rc;}void CeCosTest::SetTimeouts (Duration dActive,Duration dDownload/*,Duration dElapsed*/){ m_ep.SetActiveTimeout (dActive); m_ep.SetDownloadTimeout(dDownload);/* m_ep.SetElapsedTimeout (dElapsed);*/}void CeCosTest::CloseSocket (){ delete m_pSock; m_pSock=0;}bool CeCosTest::AtPrompt(){ const String strPrompt(m_ep.Platform()->Prompt()); unsigned int nPromptLen=_tcslen(strPrompt); return nPromptLen>0 && m_strOutput.size()>=nPromptLen && 0==_tcscmp((LPCTSTR)m_strOutput+m_strOutput.size()-nPromptLen,strPrompt);}#ifdef _WIN32BOOL WINAPI HandlerRoutine( DWORD dwCtrlType // control signal type ){ dwCtrlType; // eliminate compiler warning return TRUE;}#endifbool CeCosTest::InteractiveInferior(LPCTSTR pszHostPort,TCHAR **argv){ bool rc=false; if(_TCHAR('\0')!=*pszHostPort){ if(!CeCosSocket::IsLegalHostPort(pszHostPort)){ ERROR(_T("Illegal host:port '%s'\n"),pszHostPort); return false; } else { m_strExecutionHostPort=pszHostPort; 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); String strInferior(m_ep.Platform()->Prefix()); strInferior+=_T("-gdb");#ifdef _WIN32 SetConsoleCtrlHandler(HandlerRoutine,TRUE); int n=_tspawnvp(_P_WAIT,strInferior,argv); if(-1==n){ Log(_T("Failed to spawn %s\n"),(LPCTSTR)strInferior); } 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(strInferior,argv); Log(_T("Error invoking %s - %s\n"),(LPCTSTR)strInferior,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("Inferior 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"));}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;}void CeCosTest::InferiorOutputFunc(LPCTSTR pszMsg){ LogString(pszMsg); m_nOutputLen+=_tcslen(pszMsg); if(m_pspPipe){ m_pspPipe->Send(pszMsg); } if(m_nOutputLen>20000){ LogString(_T("\n>>>> Infra FAIL\n*** too much output ***\n>>>>\n")); SetStatus(Fail); m_psp->Kill(); } m_tBase=InferiorTime(); // We are seeing life, so reset the clock for timeouts if(AtPrompt()){ // gdb's output included one or more prompts // Send another command along if(m_nCmdIndex>=m_arstrInferiorCmds.size()){ // Nothing further to say to gdb - exit m_psp->Kill(); // case 3 } else { if(m_nCmdIndex>0 && 0==_tcscmp(_T("load"),m_arstrInferiorCmds[m_nCmdIndex-1])){ // load command was previous command - we are no longer downloading m_bDownloading=false; } String strCmd(m_arstrInferiorCmds[m_nCmdIndex++]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -