diff -r 000000000000 -r 96e5fb8b040d kerneltest/e32utils/trace/btrace.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32utils/trace/btrace.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,455 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32utils\trace\btrace.cpp +// +// + +#include +#include +#include + +CConsoleBase* Console; +extern RBTrace Trace; + +#undef ASSERT +#define ASSERT(c) (void)((c)||(AssertFailed(__LINE__))) + +TInt AssertFailed(TInt aLine) + { + _LIT(KPanicCategory,"ASSERT"); + User::Panic(KPanicCategory,aLine); + return 0; + } + + +int strlen(const char* string) + { + int len=0; + while(string[len]) ++len; + return len; + } + + +class TDesTruncate : public TDes8Overflow { void Overflow(TDes8&) {}; } IgnoreOverflow; + +void printf(const char* aFormat,...) + { + TPtrC8 formatDes((TUint8*)aFormat,strlen(aFormat)); + VA_LIST list; + VA_START(list, aFormat); + TBuf16<0x100> buffer; + // coverity[uninit_use_in_call] + ((TDes8&)buffer).AppendFormatList(formatDes, list, &IgnoreOverflow); + Console->Write(((TDes8&)buffer).Expand()); + } + + +TInt getch() + { + TRequestStatus keyStat; + Console->Read(keyStat); + User::WaitForRequest(keyStat); + return Console->KeyCode(); + } + + +TInt getch(TInt aTimeout) + { + TRequestStatus keyStat; + Console->Read(keyStat); + RTimer timer; + TInt r=timer.CreateLocal(); + ASSERT(r==KErrNone); + TRequestStatus timerStat; + timer.After(timerStat,aTimeout*1000000); + User::WaitForRequest(timerStat,keyStat); + TInt key = -1; + if(keyStat!=KRequestPending) + key = Console->KeyCode(); + timer.Cancel(); + Console->ReadCancel(); + User::WaitForAnyRequest(); + return key; + } + + +int Main(int argc, char** argv); + + +void exit_btrace(int result) + { + User::Exit(result); + } + + +TInt E32Main() + { + // create console... + TFileName exeFile = RProcess().FileName(); + TRAPD(r, Console = Console::NewL(exeFile,TSize(KConsFullScreen,KConsFullScreen))); + ASSERT(r==KErrNone); + + // get command-line... + RBuf clDes; + ASSERT(clDes.Create(User::CommandLineLength()+1)==KErrNone); + User::CommandLine(clDes); + char* cl = (char*)clDes.Collapse().PtrZ(); // convert to null terminated C string + + // split up args... + RPointerArray argArray; + ASSERT(KErrNone==argArray.Append(exeFile.Collapse().Ptr())); // first arg is program name + for(;;) + { + while((unsigned)(*cl-1)<(unsigned)' ') ++cl; // skip whitespace + if(!*cl) break; + ASSERT(KErrNone==argArray.Append(cl)); + while(*++cl>' ') {}; // skip non-whitespace + if(!*cl) break; + *cl++ = 0; // add null terminator to arg + } + + // call main... + return Main(argArray.Count(),(char**)&argArray[0]); + } + + +int Error() + { + getch(5); // pause for a while + exit_btrace(-1); + return 0; + } + + +char* FileName = 0; +char* PrimaryFilterArg = NULL; +bool SetFilter2 = false; +RArray Filter2; +bool SetMode = false; +unsigned Mode = 0; +bool SetBufferSize = false; +unsigned BufferSize = 0; +bool DumpToDebugPort = false; +TInt AnalysisLevel = 0; +bool Analyse = false; +bool DiscardOldData = true; + +RFs Fs; +RFile File; +void RePrime(); + +void Dump() + { + TUint oldMode = Trace.Mode(); + Trace.SetMode(0); // turn off trace capture while we dump + + TUint8* data; + TInt size; + while((size=Trace.GetData(data))!=0) + { + if(FileName) + { + TInt r=File.Write(TPtrC8(data,size)); + if(r!=KErrNone) + { + printf("Error writing to file (1). (Code %d)",r); + Error(); + } + } + if(DumpToDebugPort) + { + do + { + int s = size; + if(s>256) s=256; + RDebug::RawPrint(TPtrC8(data,s)); + data += s; + size -= s; + } + while(size); + } + Trace.DataUsed(); + } + // Flush the file here so we can be sure to detect whether the btrace data + // has been written successfully to the file. + if (FileName) + { + // Flush the file here so we can be sure to detect whether the btrace data + // has been written successfully to the file. + TInt r = File.Flush(); + if (r != KErrNone) + { + printf("Error writing to file (2). (Code %d)",r); + Error(); + } + File.Close(); + } + + Trace.SetMode(oldMode); + RePrime(); + } + +bool SetFilter(char* args); +void DoAnalyse(TInt aAnalysisLevel); + +int DoCommand() + { + + if(SetBufferSize) + Trace.ResizeBuffer(BufferSize*1024); + + if(SetMode) + Trace.SetMode(Mode); + + if (PrimaryFilterArg) + SetFilter(PrimaryFilterArg); + + if(SetFilter2) + { + TInt r = Trace.SetFilter2(&Filter2[0], Filter2.Count()); + if(r<0) + { + printf("Error setting secondary filter. (%d)",r); + Error(); + } + if (DiscardOldData) + Trace.Empty(); // discard old data + } + + if(FileName || DumpToDebugPort) + Dump(); + + if(Analyse) + DoAnalyse(AnalysisLevel); + + return 0; + } + + +unsigned int ParseDecimal(char*& args) + { + unsigned int i=0; + unsigned int d; + while((d=*args-'0')<10u) + { + ++args; + i = i*10+d; + } + return i; + } + + +bool SetFilter(char* args) + { + unsigned i; + // Turn everything off and discard old data + for(i=0; i<256; i++) + { + Trace.SetFilter(i,0); + } + if (DiscardOldData) + Trace.Empty(); + + // Iterate over comma-seperated filter numbers + bool set_metatrace = false; + while((unsigned)(*args-'0')<10u) + { + unsigned int i = ParseDecimal(args); + if(i>=256) + { + printf("Primary filter value out of range"); + Error(); + } + if (!set_metatrace) + { + set_metatrace = true; + Trace.SetFilter(BTrace::EMetaTrace,1); + } + Trace.SetFilter(i,1); + if(*args==',') + ++args; + } + return (*args==0); + } + + +bool ParseFilter2(char* args) + { + while((unsigned)(*args-'0') < 10u) + { + unsigned int i = ParseDecimal(args); + TInt r = Filter2.Append(i); + if(r<0) + { + printf("Error parsing secondary filter. (%d)",r); + Error(); + } + if(*args==',') + { + ++args; + } + } + return SetFilter2=(*args==0); + } + + +bool ParseMode(char* args) + { + Mode = ParseDecimal(args); + return SetMode=(*args==0); + } + + +bool ParseBufferSize(char* args) + { + BufferSize = ParseDecimal(args); + return SetBufferSize=(*args==0); + } + + +bool ParseAnalyse(char* args) + { + AnalysisLevel = ParseDecimal(args); + return Analyse=(*args==0); + } + + +int CreateFile(char* name) + { + if(FileName) + { + printf("Too many arguments"); + return Error(); + } + + FileName = name; + unsigned nameLen = strlen(name); + if(nameLen>(unsigned)KMaxFileName) + { + printf("File name too long.\n"); + return Error(); + } + + TInt r; + if(!Fs.Handle()) + { + r = Fs.Connect(); + if(r!=KErrNone) + { + printf("Couldn't connect to file server. (%d)\n",r); + return Error(); + } + } + + TBuf8 fn = TPtrC8((TUint8*)name,nameLen); + r = File.Replace(Fs,fn.Expand(),EFileWrite); + if(r!=KErrNone) + { + printf("Couldn't create file: %s. (%d)\n",name,r); + return Error(); + } + + return 0; + } + + +int Help() + { + printf("Usage: BTRACE [options] [filename]\n"); + printf("\n"); + printf("Options:\n"); + printf("-fLIST Set primary filter to a LIST of comma separated category numbers.\n"); + printf(" This argument may be used more than once e.g. -f1,22,3 -f44 \n"); + printf("-sLIST Set secondary filter to a LIST of comma separated UID values.\n"); + printf(" This argument may be used more than once e.g. -s1221,22,343243 -s3242344 \n"); + printf("-mN Set capture mode to value N (See RBTrace::TMode)\n"); + printf("-bN Set capture buffer size to N kBytes\n"); + printf("-d Dump contents of trace buffer to debug port\n"); + printf("-tsNAME Output a test measurement start trace with text NAME. This text\n"); + printf(" may be between 0 and 80 non-whitespace characters.\n"); + printf("-te Output a test measurement end trace\n"); + printf("-aLEVEL Analyse trace buffer and produce a report. UNSUPPORTED!\n"); + printf("-k Keep old contents of trace buffer when enabling a new filter\n"); + printf("filename File to dump contents of trace buffer to.\n"); + getch(); + return 0; + } + + +int Main(int argc, char** argv) + { + if(argc<=1) + return Help(); + + TInt r = Trace.Open(); + if(r!=KErrNone) + { + printf("Couldn't open BTrace driver. (Code %d)",r); + Error(); + return r; + } + + char* a; + while(--argc) + { + a = *++argv; + if(a[0]!='-') + { + CreateFile(a); + continue; + } + + int r=0; + switch(a[1]) + { + case 'f': PrimaryFilterArg = a+2; r = true; break; + case 's': r=ParseFilter2(a+2); break; + case 'm': r=ParseMode(a+2); break; + case 'b': r=ParseBufferSize(a+2); break; + case 'd': r=a[2]==0; DumpToDebugPort = true; break; + case 't': + { + if (a[2]=='s') + { + TUint cch=strlen(a); + if (cch > KMaxBTraceDataArray) + cch = KMaxBTraceDataArray; + int buff[KMaxBTraceDataArray/sizeof(int)]; + a+=3; + memcpy(buff, a, cch); + BTraceContextN(BTrace::EMetaTrace, BTrace::EMetaTraceMeasurementStart, 0,0, buff, cch); + r=1; + } + else if (a[2]=='e') + { + BTraceContext8(BTrace::EMetaTrace, BTrace::EMetaTraceMeasurementEnd, 0,0); + r=1; + } + } + break; + case 'a': r=ParseAnalyse(a+2); break; + case 'k': DiscardOldData = false; r = true; break; + default: break; + } + + if(!r) + { + printf("Bad command line argument: %s",a); + Error(); + } + } + + return DoCommand(); + } +