diff -r 000000000000 -r 7f656887cf89 commands/btrace/btrace.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/btrace/btrace.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,508 @@ +// btrace.cpp +// +// Copyright (c) 2007 - 2010 Accenture. All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the "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: +// Accenture - Initial contribution +// + +#include "btrace.h" + +#if defined(FSHELL_MEMORY_ACCESS_SUPPORT) +#define TEXT_TRACE_MODE_SUPPORTED +#endif + +const TInt KMaxCategories = 256; +const TUint KPrimingStopped = 0x102864BC; + + + +CCommandBase* CCmdBtrace::NewLC() + { + CCmdBtrace* self = new(ELeave) CCmdBtrace(); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +CCmdBtrace::~CCmdBtrace() + { + iPrimaryFilters.Close(); + iSecondaryFilters.Close(); + iBtrace.Close(); + } + +CCmdBtrace::CCmdBtrace() + : iThreshold(50) + { + } + +void CCmdBtrace::ConstructL() + { + BaseConstructL(); + } + +const TDesC& CCmdBtrace::Name() const + { +#ifdef BUILDING_ATRACE + _LIT(KName, "atrace"); +#else + _LIT(KName, "btrace"); +#endif + return KName; + } + +#define CASE_LIT(x) case BTrace:: x : { _LIT(KName, #x); return &KName; } +#define CASE_REALLY_LIT(x) case x : { _LIT(KName, #x); return &KName; } + +const TDesC* BtraceCategoryName(TInt aCategory) + { + switch (aCategory) + { + CASE_LIT(ERDebugPrintf) + CASE_LIT(EKernPrintf) + CASE_LIT(EPlatsecPrintf) + CASE_LIT(EThreadIdentification) + CASE_LIT(ECpuUsage) + CASE_LIT(EKernPerfLog) + CASE_LIT(EClientServer) + CASE_LIT(ERequests) + CASE_LIT(EChunks) + CASE_LIT(ECodeSegs) + CASE_LIT(EPaging) + CASE_LIT(EThreadPriority) + CASE_LIT(EPagingMedia) + CASE_LIT(EKernelMemory) + CASE_LIT(EHeap) + CASE_LIT(EMetaTrace) + CASE_LIT(ERamAllocator) + CASE_LIT(EFastMutex) + CASE_LIT(EProfiling) + CASE_REALLY_LIT(ExtraBTrace::EPubSub) + CASE_REALLY_LIT(ExtraBTrace::EFfsTrace) + CASE_LIT(EPlatformSpecificFirst) + CASE_LIT(EPlatformSpecificLast) + CASE_LIT(ESymbianExtentionsFirst) + CASE_LIT(ESymbianExtentionsLast) + CASE_LIT(ETest1) + CASE_LIT(ETest2) + default: + { + _LIT(KUnknown, "?"); + return &KUnknown; + } + } + } + +void CCmdBtrace::DoRunL() + { +#ifdef TEXT_TRACE_MODE_SUPPORTED + if (iOptions.IsPresent(&iTextTraceMode)) + { + LoadMemoryAccessL(); + const TInt ESerialOutMask = 3; // As per kernel.h + TInt err = iMemAccess.SetTextTraceMode(iTextTraceMode, ESerialOutMask); + LeaveIfErr(err, _L("Couldn't set text trace mode")); + } +#endif + + TInt i; + LeaveIfErr(iBtrace.Open(), _L("Couldn't open RBTrace")); + + if (iOptions.IsPresent(&iReset)) + { + ResetL(); + } + + if (iOptions.IsPresent(&iBufferSize)) + { + iBtrace.ResizeBuffer(iBufferSize * 1024); + } + + if (iOptions.IsPresent(&iMode)) + { + SetMode(iMode); + } + + iBtrace.SetTimestamp2Enabled(iEnableTimestamp2); + + const TInt numPrimaryFilters = iPrimaryFilters.Count(); + if (numPrimaryFilters > 0) + { + RemovePrimaryFilters(); + EmptyBuffer(); + + // Enable the specified categories. + for (i = 0; i < numPrimaryFilters; ++i) + { + iBtrace.SetFilter(iPrimaryFilters[i], 1); + } + } + if (iTest) + { + TestL(); + return; + } + + const TInt numSecondaryFilters = iSecondaryFilters.Count(); + if (numSecondaryFilters > 0) + { + TUint32* filterArray = new(ELeave) TUint32[iSecondaryFilters.Count()]; + for (i = 0; i < numSecondaryFilters; ++i) + { + filterArray[i] = iSecondaryFilters[i]; + } + + TInt err = iBtrace.SetFilter2(filterArray, numSecondaryFilters); + if (err) + { + PrintError(err, _L("Couldn't set secondary filter")); + } + else + { + // Discard old data. + EmptyBuffer(); + } + + delete[] filterArray; + } + + if (numPrimaryFilters > 0 || numSecondaryFilters > 0) + { + BTrace8(BTrace::EMetaTrace, BTrace::EMetaTraceMeasurementEnd, KPrimingStopped, KPrimingStopped); + } + + if (iFileName.Length()) + { + RFile file; + User::LeaveIfError(file.Replace(FsL(), iFileName, EFileWrite)); + file.Close(); + } + + if (iFileName.Length() || iDumpToRdebug) + { + if (iFollow) + { + if (iThreshold > 100) + { + PrintError(KErrArgument, _L("Invalid threshold percentage")); + User::Leave(KErrArgument); + } + Printf(_L("Hit any key to abort waiting and flush buffer...\r\n")); + TInt bytesRequired = (iBtrace.BufferSize() * iThreshold) / 100; + TBool finished(EFalse); + while (!finished) + { + TRequestStatus btraceStatus; + iBtrace.RequestData(btraceStatus, bytesRequired); + TRequestStatus keyStatus; + Stdin().WaitForKey(keyStatus); + if (iVerbose) + { + Printf(_L("Waiting for %d bytes in buffer\r\n"), bytesRequired); + } + User::WaitForRequest(btraceStatus, keyStatus); + if (keyStatus == KRequestPending) + { + Stdin().WaitForKeyCancel(); + User::WaitForRequest(keyStatus); + User::LeaveIfError(btraceStatus.Int()); + } + else + { + iBtrace.CancelRequestData(); + User::WaitForRequest(btraceStatus); + finished = ETrue; + } + + DumpL(); + } + } + else + { + DumpL(); + } + } + + if (iVerbose || (iFileName.Length() == 0)) + { + Printf(_L("Buffer size: %d\r\n"), iBtrace.BufferSize()); + Printf(_L("Mode: %S (%u)\r\n"), ModeText(iBtrace.Mode()), iBtrace.Mode()); +#ifdef TEXT_TRACE_MODE_SUPPORTED + LoadMemoryAccessL(); + TUint traceMode = 0; + TInt err = iMemAccess.SetTextTraceMode(traceMode, 0); + if (err) + { + PrintWarning(_L("Couldn't read text trace mode: err=%d"), err); + } + else + { + _LIT(KHuh, ""); + const TDesC* name = &KHuh; +#define CASE_LIT2(x, y) case x: { _LIT(KName, #y); name = &KName; break; } + switch (traceMode) + { + CASE_LIT2(0, ESerialOutDefault) + CASE_LIT2(1, ESerialOutNever) + CASE_LIT2(2, ESerialOutAlways) + default: + break; + } + Printf(_L("Text trace mode: %S (%d)\r\n"), name, traceMode); + } +#endif + Printf(_L("Primary filters:\r\n")); + TBool foundOne(EFalse); + for (TInt i = 0; i < KMaxCategories; ++i) + { + if (iBtrace.Filter(i) == 1) + { + Printf(_L("\t%d (%S)\r\n"), i, BtraceCategoryName(i)); + foundOne = ETrue; + } + } + if (!foundOne) + { + Write(_L("\tnone\r\n")); + } + Printf(_L("Secondary filters: ")); + TInt globalFilter; + TUint32* uids; + TInt ret = iBtrace.Filter2(uids, globalFilter); + if (ret >= 0) + { + if (globalFilter) + { + Printf(_L("[Secondary filters accept]\r\n")); + } + else + { + Printf(_L("[Secondary filters reject]\r\n")); + } + if (ret > 0) + { + for (TInt i = 0; i < ret; ++i) + { + Printf(_L("\t0x%08x\r\n"), uids[i]); + } + } + else + { + Write(_L("\tnone\r\n")); + } + delete uids; + } + else + { + PrintError(ret, _L("Unable to read secondary filters")); + } + } + } + +void CCmdBtrace::DumpL() + { + RFile file; + if (iFileName.Length()) + { + if (iVerbose) + { + Printf(_L("Opening \"%S\"\r\n"), &iFileName); + } + User::LeaveIfError(file.Open(FsL(), iFileName, EFileWrite)); + CleanupClosePushL(file); + TInt pos = 0; + User::LeaveIfError(file.Seek(ESeekEnd, pos)); + } + + TUint8* data; + TInt size; + TInt err = KErrNone; + while ((size = iBtrace.GetData(data)) != 0) + { + if (file.SubSessionHandle() && (err == KErrNone)) + { + if (iVerbose) + { + Printf(_L("Writing %d bytes to \"%S\"\r\n"), size, &iFileName); + } + err = file.Write(TPtrC8(data,size)); + if (err) + { + PrintError(err, _L("Couldn't write to file")); + } + } + + if (iDumpToRdebug) + { + if (iVerbose) + { + Printf(_L("Writing %d bytes to LtkUtils::HexDumpToRDebug\r\n"), size); + } + LtkUtils::HexDumpToRDebug(TPtrC8(data, size)); + } + + iBtrace.DataUsed(); + } + + User::LeaveIfError(err); + if (iFileName.Length()) + { + CleanupStack::PopAndDestroy(&file); + } + } + +void CCmdBtrace::ArgumentsL(RCommandArgumentList& aArguments) + { + _LIT(KArgFiles, "file_name"); + aArguments.AppendFileNameL(iFileName, KArgFiles); + } + +void CCmdBtrace::OptionsL(RCommandOptionList& aOptions) + { + _LIT(KOptPrimaryFilter, "filter"); + aOptions.AppendUintL(iPrimaryFilters, KOptPrimaryFilter); + + _LIT(KOptSecondaryFilter, "secondary"); + aOptions.AppendUintL(iSecondaryFilters, KOptSecondaryFilter); + + _LIT(KOptMode, "mode"); + aOptions.AppendUintL(iMode, KOptMode); + + _LIT(KOptBufferSize, "buffer"); + aOptions.AppendUintL(iBufferSize, KOptBufferSize); + + _LIT(KOptDump, "dump"); + aOptions.AppendBoolL(iDumpToRdebug, KOptDump); + + _LIT(KOptFollow, "follow"); + aOptions.AppendBoolL(iFollow, KOptFollow); + + _LIT(KOptThreshold, "threshold"); + aOptions.AppendUintL(iThreshold, KOptThreshold); + + _LIT(KOptTimestamp2, "timestamp2"); + aOptions.AppendBoolL(iEnableTimestamp2, KOptTimestamp2); + + _LIT(KOptVerbose, "verbose"); + aOptions.AppendBoolL(iVerbose, KOptVerbose); + + _LIT(KOptTest, "test"); + aOptions.AppendBoolL(iTest, KOptTest); + + _LIT(KOptReset, "reset"); + aOptions.AppendBoolL(iReset, KOptReset); + +#ifdef TEXT_TRACE_MODE_SUPPORTED + _LIT(KOptTextTraceMode, "text-trace-mode"); + aOptions.AppendUintL(iTextTraceMode, KOptTextTraceMode); +#endif + } + +#ifdef EXE_BUILD +EXE_BOILER_PLATE(CCmdBtrace) +#endif + +void CCmdBtrace::TestL() + { + SetMode(RBTrace::EEnable); + EmptyBuffer(); + iBtrace.SetFilter(BTrace::ESymbianExtentionsFirst, 1); + _LIT8(KHello, "Hello world of btrace!!!"); + TInt res = BTraceBig(BTrace::ESymbianExtentionsFirst, 0, 0, KHello().Ptr(), KHello().Size()); + Printf(_L8("Writing text '%S' to btrace returned %d...\r\n"), &KHello, res); + + TUint8* data; + TInt size; + TInt err = KErrNotFound; + while ((size = iBtrace.GetData(data)) != 0 && err == KErrNotFound) + { + Printf(_L("Read a buffer of size %d\r\n"), size); + TPtrC8 ptr(data, size); + if (ptr.Find(KHello) >= 0) + { + Printf(_L("Found text ok.\r\n")); + err = KErrNone; + } + } + if (err == KErrNotFound) + { + Printf(_L("Failed to find the test data\r\n")); + } + } + +void CCmdBtrace::ResetL() + { + SetMode(0); + EmptyBuffer(); + RemovePrimaryFilters(); + RemoveSecondaryFiltersL(); + } + +void CCmdBtrace::SetMode(TUint aMode) + { + if (iVerbose) + { + Printf(_L("Setting mode to \"%S\" (%u)\r\n"), ModeText(aMode), aMode); + } + + iBtrace.SetMode(aMode); + } + +void CCmdBtrace::EmptyBuffer() + { + if (iVerbose) + { + Write(_L("Discarding contents of trace buffer...\r\n")); + } + + iBtrace.Empty(); + } + +void CCmdBtrace::RemovePrimaryFilters() + { + if (iVerbose) + { + Write(_L("Removing all primary filters...\r\n")); + } + + for (TInt i = 0; i < KMaxCategories; ++i) + { + iBtrace.SetFilter(i, 0); + } + } + +void CCmdBtrace::RemoveSecondaryFiltersL() + { + if (iVerbose) + { + Write(_L("Removing all secondary filters...\r\n")); + } + + LeaveIfErr(iBtrace.SetFilter2((const TUint32*)NULL, 0), _L("Couldn't remove all secondary filters")); + } + +const TDesC* CCmdBtrace::ModeText(TUint aMode) const + { + _LIT(KDisabled, "disabled"); + _LIT(KEnabled, "enabled"); + _LIT(KFreeRunning, "enabled and free running"); + _LIT(KUnknown, "unknown"); + + switch (aMode) + { + case 0: + return &KDisabled; + case RBTrace::EEnable: + return &KEnabled; + case RBTrace::EEnable | RBTrace::EFreeRunning: + return &KFreeRunning; + default: + return &KUnknown; + } + } +