--- /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 <e32cons.h>
+#include <f32file.h>
+#include <d32btrace.h>
+
+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<TAny> 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<TUint32> 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<KMaxFileName*2> 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();
+ }
+