# HG changeset patch # User Tom Sutcliffe # Date 1287696779 -3600 # Node ID dc41da2f70a462743433fe00795fab45c607e14e # Parent 849a0b46c767495c9b4cac0fff03b88d339c945c Added showdebug command. Also: * Added an exported constructor to RChildProcess so the iProcess handle was set to zero on construction. * Fixed bug in fshell_builddocs script that created HTML relative links with backslashes instead of forward slashes. diff -r 849a0b46c767 -r dc41da2f70a4 build/common/common.mmh --- a/build/common/common.mmh Sun Oct 17 18:43:12 2010 +0100 +++ b/build/common/common.mmh Thu Oct 21 22:32:59 2010 +0100 @@ -570,6 +570,7 @@ #define FSHELL_UID_VT100TCPCONS 0x10286F89 #define FSHELL_UID_VT100USBCONS 0x10286F8A #define FSHELL_UID_WIN32CONS 0x10286F8B +#define FSHELL_UID_SHOWDEBUG 0x10286F8D #else // Not FSHELL_PROTECTED_UIDS @@ -723,6 +724,7 @@ #define FSHELL_UID_VT100TCPCONS 0xE0286F89 #define FSHELL_UID_VT100USBCONS 0xE0286F8A #define FSHELL_UID_WIN32CONS 0xE0286F8B +#define FSHELL_UID_SHOWDEBUG 0xE0286F8D #endif // FSHELL_PROTECTED_UIDS diff -r 849a0b46c767 -r dc41da2f70a4 build/s60/fshell_platform.iby --- a/build/s60/fshell_platform.iby Sun Oct 17 18:43:12 2010 +0100 +++ b/build/s60/fshell_platform.iby Thu Oct 21 22:32:59 2010 +0100 @@ -20,7 +20,11 @@ ;localised vendor names %{"Accenture"} +#ifdef FSHELL_OPEN_SIGNED +HASH{"fshell (S60 Open Signed)"},(FSHELL_UID_SIS),FSHELL_VERSION,0,FSHELL_TIMESTAMP,TYPE=SA +#else HASH{"fshell (S60)"},(FSHELL_UID_SIS),FSHELL_VERSION,0,FSHELL_TIMESTAMP,TYPE=SA +#endif [0x101F7961], 0, 0, 0, {"Series60ProductID"} [0x102032BE], 0, 0, 0, {"Series60ProductID"} diff -r 849a0b46c767 -r dc41da2f70a4 commands/ecom/ecom.cpp --- a/commands/ecom/ecom.cpp Sun Oct 17 18:43:12 2010 +0100 +++ b/commands/ecom/ecom.cpp Thu Oct 21 22:32:59 2010 +0100 @@ -123,9 +123,9 @@ { TUid implKey; // We don't care about this TAny* impl = NULL; - TRAPL(impl = REComSession::CreateImplementationL(uid, implKey), _L("Couldn't instanciate plugin uid 0x%x"), iUid); + TRAPL(impl = REComSession::CreateImplementationL(uid, implKey), _L("Couldn't instantiate plugin uid 0x%x"), iUid); if (impl == NULL) LeaveIfErr(KErrGeneral, _L("Plugin returned NULL implementation pointer!")); - Printf(_L("Instanciated plugin 0x%x ok.\r\n"), iUid); + Printf(_L("Instantiated plugin 0x%x ok.\r\n"), iUid); #ifdef FSHELL_MEMORY_ACCESS_SUPPORT if (iVerbose) diff -r 849a0b46c767 -r dc41da2f70a4 commands/group/bld.inf --- a/commands/group/bld.inf Sun Oct 17 18:43:12 2010 +0100 +++ b/commands/group/bld.inf Thu Oct 21 22:32:59 2010 +0100 @@ -452,3 +452,10 @@ PRJ_MMPFILES ..\testexecute\testexecute.mmp #endif + +#ifdef FSHELL_CLOGGER_SUPPORT_DEBUG_ROUTER +PRJ_EXPORTS +..\showdebug\showdebug.cif z:\resource\cif\fshell\showdebug.cif +PRJ_MMPFILES +..\showdebug\showdebug.mmp +#endif diff -r 849a0b46c767 -r dc41da2f70a4 commands/group/fshell_commands.iby --- a/commands/group/fshell_commands.iby Sun Oct 17 18:43:12 2010 +0100 +++ b/commands/group/fshell_commands.iby Thu Oct 21 22:32:59 2010 +0100 @@ -377,4 +377,9 @@ FSHELL_EXECUTABLE_FILE(snake.exe) FSHELL_COMMAND_INFO_FILE(fshell,snake.cif) +#ifdef FSHELL_CLOGGER_SUPPORT_DEBUG_ROUTER +FSHELL_EXECUTABLE_FILE(showdebug.exe) +FSHELL_COMMAND_INFO_FILE(fshell,showdebug.cif) +#endif + #endif // __FSHELL_COMMANDS_IBY__ diff -r 849a0b46c767 -r dc41da2f70a4 commands/showdebug/showdebug.cif --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/showdebug/showdebug.cif Thu Oct 21 22:32:59 2010 +0100 @@ -0,0 +1,47 @@ +# showdebug.cif +# +# Copyright (c) 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 +# + +==name showdebug + +==short-description + +Redirects RDebug::Print to the console. + +==long-description + +Uses the clogger debugrouter LDD to intercept Kern::Printf and RDebug::Print calls and redirect them to the console. Similar to C but without all the features clogger layers on top, more focussed on just printing the rdebug data. + +There can only be one client of the clogger debugrouter, which means you cannot run multiple instances of the showdebug command at the same time. + +==argument string process optional + +If specified, showdebug will launch the given process and redirect RDebug until the process exits. If not specified it will do so indefinitely or until CTRL-C is pressed. + +==argument string arguments optional last + +Arguments to pass to process. + +==option bool v verbose multiple + +If specified, the timestamp and the originating thread of each trace are also printed. If specified twice (ie -vv) thread IDs are additionally expanded to full thread names. + +==option bool f filter + +Only display traces that came directly from threads belonging to the process you specified. Use with caution, you may miss traces that are I your process but not directly emitted I it. If the origin of a trace cannot be identified it will be shown even if C<--filter> is specified. + +==see-also + +L + +==copyright + +Copyright (c) 2010 Accenture. All rights reserved. diff -r 849a0b46c767 -r dc41da2f70a4 commands/showdebug/showdebug.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/showdebug/showdebug.cpp Thu Oct 21 22:32:59 2010 +0100 @@ -0,0 +1,298 @@ +// showdebug.cpp +// +// Copyright (c) 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 +#include +#include +#include + +using namespace IoUtils; + +class CCmdShowDebug : public CCommandBase, public MCommandExtensionsV2 + { +public: + static CCommandBase* NewLC(); + ~CCmdShowDebug(); +private: + CCmdShowDebug(); + void Log(TUint8 aWhere, TUint32 aTickCount, TUint aThreadId, const TDesC8& aMsg); + inline TTime TickCountToTime(TUint32 aTickCount) const; + +private: // From CCommandBase. + virtual const TDesC& Name() const; + virtual void DoRunL(); + virtual void ArgumentsL(RCommandArgumentList& aArguments); + virtual void OptionsL(RCommandOptionList& aOptions); + virtual void DoCancel(); + virtual void RunL(); + +private: // From MCommandExtensionsV2 + virtual void CtrlCPressed(); + + + class CLogonCompleter : public CActive + { + public: + CLogonCompleter(CCmdShowDebug* aCommand) : CActive(CActive::EPriorityStandard), iCommand(aCommand) + { + CActiveScheduler::Add(this); + iCommand->iProcess.Process().Logon(iStatus); + SetActive(); + } + void RunL() { iCommand->Complete(iStatus.Int()); } + void DoCancel() { iCommand->iProcess.Process().LogonCancel(iStatus); } + ~CLogonCompleter() { Cancel(); } + + private: + CCmdShowDebug* iCommand; + }; + +private: + RCloggerDebugRouter iRouter; + RChunk iChunk; + TBuf8<2048> iTempBuf; + TBuf<2048> iTempWideBuf; + RChildProcess iProcess; + CLogonCompleter* iCompleter; + TInt64 iStartupTickInMicroseconds; + TTime iTimeAtStartup; + TInt iTickFreq; + + HBufC* iProcessName; + HBufC* iArgs; + RArray iVerbose; + TBool iFilter; + }; + +EXE_BOILER_PLATE(CCmdShowDebug) + +CCommandBase* CCmdShowDebug::NewLC() + { + CCmdShowDebug* self = new(ELeave) CCmdShowDebug(); + CleanupStack::PushL(self); + self->BaseConstructL(); + return self; + } + +CCmdShowDebug::~CCmdShowDebug() + { + Cancel(); + if (iRouter.Handle()) + { + iRouter.EnableDebugRouting(RCloggerDebugRouter::EDisable); + } + iRouter.Close(); + iChunk.Close(); + delete iCompleter; + if (iProcess.Process().Handle() && iProcess.Process().ExitType() == EExitPending) + { + iProcess.Process().Kill(KErrAbort); + } + iProcess.Close(); + delete iProcessName; + delete iArgs; + } + +CCmdShowDebug::CCmdShowDebug() + : CCommandBase(EManualComplete | ECaptureCtrlC) + { + SetExtension(this); + } + +const TDesC& CCmdShowDebug::Name() const + { + _LIT(KName, "showdebug"); + return KName; + } + +void CCmdShowDebug::ArgumentsL(RCommandArgumentList& aArguments) + { + aArguments.AppendStringL(iProcessName, _L("process")); + aArguments.AppendStringL(iArgs, _L("arguments")); + } + +void CCmdShowDebug::OptionsL(RCommandOptionList& aOptions) + { + aOptions.AppendBoolL(iVerbose, _L("verbose")); + aOptions.AppendBoolL(iFilter, _L("filter")); + } + +void CCmdShowDebug::DoRunL() + { + TInt err = RCloggerDebugRouter::LoadDriver(); + if (err != KErrAlreadyExists) LeaveIfErr(err, _L("Couldn't load clogger debug router")); + LeaveIfErr(iRouter.Open(), _L("Couldn't open debug router")); + LeaveIfErr(iRouter.OpenChunk(iChunk), _L("Couldn't open debug router shared chunk")); + LeaveIfErr(iRouter.EnableDebugRouting(RCloggerDebugRouter::EEnableRouting), _L("Couldn't enable routing")); + + iRouter.ReceiveData(iStatus); + SetActive(); + + if (iProcessName) + { + TRAPL(iProcess.CreateL(*iProcessName, iArgs ? *iArgs : KNullDesC(), IoSession(), Stdin(), Stdout(), Stderr(), Env()), _L("Failed to execute %S"), iProcessName); + iCompleter = new(ELeave) CLogonCompleter(this); + SetErrorReported(ETrue); // So that if iProcess completes with an error it doesn't cause a strange printout when we complete with its error code + iProcess.Process().Resume(); + } + + if (iVerbose.Count()) + { + // Need to do some maths to figure out how to translate tick counts to time + TUint32 tickCount = User::NTickCount(); + iTimeAtStartup.UniversalTime(); + TInt tickPeriod; + User::LeaveIfError(HAL::Get(HAL::ENanoTickPeriod, tickPeriod)); + iTickFreq = 1000000 / tickPeriod; // We work in frequencies because they are the round numbers when using the fast counter, and at some point we might want to again + + iStartupTickInMicroseconds = ((TInt64)tickCount * 1000000) / (TInt64)iTickFreq; // Just making damn sure we're using 64bit math + } + } + +void CCmdShowDebug::DoCancel() + { + iRouter.CancelReceive(); + } + +TPtrC8 Read(TDes8& aTempBuf, TPtrC8& aData, TInt aLength, TPtrC8& aOverflowData) + { + if (aLength <= aData.Length()) + { + // Can read it from this buffer + TPtrC8 res(aData.Left(aLength)); + aData.Set(aData.Mid(aLength)); + return res; + } + else /*if (aLength > aData.Length())*/ + { + // Descriptor spans wrap point, so need to copy into temp buf + aTempBuf.Copy(aData.Left(aTempBuf.MaxLength())); // If anyone's crazy enough to write a platsec diagnostic string longer than 2k, it gets truncated + TInt overflowLen = aLength - aData.Length(); + aData.Set(aOverflowData); // Wrap aData + aOverflowData.Set(TPtrC8()); + if (overflowLen > aData.Length()) + { + ASSERT(EFalse); // Shouldn't happen + // in urel, return everything we've got + return aData; + } + aTempBuf.Append(aData.Left(overflowLen)); + aData.Set(aData.Mid(overflowLen)); + return TPtrC8(aTempBuf); + } + } + +void CCmdShowDebug::RunL() + { + TUint chunkSize = iChunk.Size(); + const TUint KDataStartOffset = sizeof(SDebugChunkHeader); + SDebugChunkHeader* chunkHeader = (SDebugChunkHeader*)iChunk.Base(); + TUint start = chunkHeader->iStartOffset; + TUint end = chunkHeader->iEndOffset; + TUint overflows = chunkHeader->iOverflows; + + TBool wrap = (start > end); + TUint endLen = wrap ? chunkSize - start : end - start; + TUint startLen = wrap ? end - KDataStartOffset : 0; + + TPtrC8 endData(iChunk.Base() + start, endLen); + TPtrC8 startData; + if (wrap) startData.Set(iChunk.Base() + KDataStartOffset, startLen); + TPtrC8 data(endData); + + while (data.Length()) + { + TPtrC8 header = Read(iTempBuf, data, sizeof(SCloggerTraceInfo), startData); + if (header.Length() < (TInt)sizeof(SCloggerTraceInfo)) + { + ASSERT(EFalse); // for udeb + break; // Something's broken + } + SCloggerTraceInfo info; + Mem::Copy(&info, header.Ptr(), sizeof(SCloggerTraceInfo)); + ASSERT(info.iTraceType == 'K' || info.iTraceType == 'U' || info.iTraceType == 'P'); + TPtrC8 msg = Read(iTempBuf, data, info.iLength, startData); + Log(info.iTraceType, info.iTickCount, info.iThreadId, msg); + } + if (overflows) + { + _LIT(KErr, "RDebug::Print buffer overflowed, %u calls not logged"); + PrintWarning(KErr, overflows); + } + + iRouter.ReceiveData(iStatus); + SetActive(); + } + +void CCmdShowDebug::Log(TUint8 /*aWhere*/, TUint32 aTickCount, TUint aThreadId, const TDesC8& aMsg) + { + RThread thread; thread.SetHandle(0); + if (iVerbose.Count() > 1 || iFilter) + { + // Need to open the thread in those cases + thread.Open(aThreadId); + } + + if (iFilter && thread.Handle()) + { + RProcess proc; + TInt err = thread.Process(proc); + if (!err) + { + if (proc.Id() != iProcess.Process().Id()) + { + // Trace definitely doesn't belong to our process, skip it + proc.Close(); + thread.Close(); + return; + } + } + } + + if (iVerbose.Count()) + { + TDateTime dt = TickCountToTime(aTickCount).DateTime(); + _LIT(KFormat, "%i-%02i-%02i %02i:%02i:%02i.%03i: "); + // Have to add 1 to Month and Day, as these are zero-based + iTempWideBuf.Format(KFormat, dt.Year(), dt.Month()+1, dt.Day()+1, dt.Hour(), dt.Minute(), dt.Second(), dt.MicroSecond()/1000); + if (iVerbose.Count() > 1 && thread.Handle()) + { + TFullName name = thread.FullName(); + iTempWideBuf.AppendFormat(_L("%S "), &name); + } + else + { + // Just use thread id + iTempWideBuf.AppendFormat(_L("[%d] "), aThreadId); + } + Write(iTempWideBuf); + } + + thread.Close(); + + iTempWideBuf.Copy(aMsg); + Write(iTempWideBuf); + Write(_L("\r\n")); + } + +void CCmdShowDebug::CtrlCPressed() + { + // TODO clean up iProcess + + Printf(_L("CTRL-C received, exiting.\r\n")); + Complete(); + } + +inline TTime CCmdShowDebug::TickCountToTime(TUint32 aTickCount) const + { + return TTime(iTimeAtStartup.Int64() + (((TInt64)aTickCount*1000000) / (TInt64)iTickFreq) - iStartupTickInMicroseconds); + } diff -r 849a0b46c767 -r dc41da2f70a4 commands/showdebug/showdebug.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/showdebug/showdebug.mmp Thu Oct 21 22:32:59 2010 +0100 @@ -0,0 +1,27 @@ +// showdebug.mmp +// +// Copyright (c) 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 + +target showdebug.exe +targettype exe +uid FSHELL_UID2_FSHELL_EXE FSHELL_UID_SHOWDEBUG +capability FSHELL_CAP_MMP_NORMAL + +userinclude . +#include +sourcepath . +source showdebug.cpp + +library euser.lib +library iocli.lib +library hal.lib diff -r 849a0b46c767 -r dc41da2f70a4 documentation/change_history.pod --- a/documentation/change_history.pod Sun Oct 17 18:43:12 2010 +0100 +++ b/documentation/change_history.pod Thu Oct 21 22:32:59 2010 +0100 @@ -28,7 +28,7 @@ =item * -Fixed crash in fed's handling of UTF-8 sequences split over a block boundary. +Fixed crash in fed's handling of UTF-8 sequences split over a block boundary. Fixed a link bug in the autogenerated documentation. =item * @@ -38,6 +38,10 @@ Added support for beagleboard to sf\3tshell platform. +=item * + +Added L command to redirect RDebug::Print()s to the console. + =back =head2 Release 001 diff -r 849a0b46c767 -r dc41da2f70a4 libraries/clogger/debugRouter/bld.inf --- a/libraries/clogger/debugRouter/bld.inf Sun Oct 17 18:43:12 2010 +0100 +++ b/libraries/clogger/debugRouter/bld.inf Thu Oct 21 22:32:59 2010 +0100 @@ -18,6 +18,7 @@ prj_exports debugRouter-kext.h \epoc32\include\fshell\debugRouter-kext.h +debugrouter.h \epoc32\include\fshell\debugRouter.h prj_mmpfiles debugRouter.mmp diff -r 849a0b46c767 -r dc41da2f70a4 libraries/iosrv/bwins/iocliu.def --- a/libraries/iosrv/bwins/iocliu.def Sun Oct 17 18:43:12 2010 +0100 +++ b/libraries/iosrv/bwins/iocliu.def Thu Oct 21 22:32:59 2010 +0100 @@ -553,4 +553,5 @@ ?SmokeTest@CCommandInfoFile@IoUtils@@QBEABVTDesC16@@XZ @ 552 NONAME ; class TDesC16 const & IoUtils::CCommandInfoFile::SmokeTest(void) const ?CifFileName@CCommandInfoFile@IoUtils@@QBEABVTDesC16@@XZ @ 553 NONAME ; class TDesC16 const & IoUtils::CCommandInfoFile::CifFileName(void) const ?GetSmokeTestStartingLineNumber@CCommandInfoFile@IoUtils@@QBEHXZ @ 554 NONAME ; int IoUtils::CCommandInfoFile::GetSmokeTestStartingLineNumber(void) const + ??0RChildProcess@IoUtils@@QAE@XZ @ 555 NONAME ; IoUtils::RChildProcess::RChildProcess(void) diff -r 849a0b46c767 -r dc41da2f70a4 libraries/iosrv/client/client_command.cpp --- a/libraries/iosrv/client/client_command.cpp Sun Oct 17 18:43:12 2010 +0100 +++ b/libraries/iosrv/client/client_command.cpp Thu Oct 21 22:32:59 2010 +0100 @@ -331,7 +331,7 @@ LeaveIfErr(iPcons.AttachWriter(iServerReadPipe, RIoPersistentConsole::EDetachOnHandleClose), _L("Cannot connect writer to persistent console %S"), &iPersistentConsoleName); iServerReader = CServerReader::NewL(iServerReadHandle, *this); - if (iServerProcess.Process().Handle() != KNullHandle && iServerProcess.Process().Handle() != RProcess().Handle()) + if (iServerProcess.Process().Handle() != KNullHandle) { // We created a new server process, but it's not yet been resumed. iServerProcess.Detach(); // Note, iServerWatch has already logged onto the process so there's no need to use RChildProcess::Run. diff -r 849a0b46c767 -r dc41da2f70a4 libraries/iosrv/client/command_base.cpp --- a/libraries/iosrv/client/command_base.cpp Sun Oct 17 18:43:12 2010 +0100 +++ b/libraries/iosrv/client/command_base.cpp Thu Oct 21 22:32:59 2010 +0100 @@ -3511,6 +3511,11 @@ aIoSession.SetObjectName(aObjHandle, name); } +EXPORT_C RChildProcess::RChildProcess() + : iProcess(0) + { + } + EXPORT_C void RChildProcess::CreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr) { DoCreateL(aExecutableName, aCommandLine, aIoSession, aStdin, aStdout, aStderr, NULL); diff -r 849a0b46c767 -r dc41da2f70a4 libraries/iosrv/eabi/iocliu.def --- a/libraries/iosrv/eabi/iocliu.def Sun Oct 17 18:43:12 2010 +0100 +++ b/libraries/iosrv/eabi/iocliu.def Thu Oct 21 22:32:59 2010 +0100 @@ -629,4 +629,6 @@ _ZNK7IoUtils16CCommandInfoFile9SmokeTestEv @ 628 NONAME _ZNK7IoUtils16CCommandInfoFile11CifFileNameEv @ 629 NONAME _ZNK7IoUtils16CCommandInfoFile30GetSmokeTestStartingLineNumberEv @ 630 NONAME + _ZN7IoUtils13RChildProcessC1Ev @ 631 NONAME + _ZN7IoUtils13RChildProcessC2Ev @ 632 NONAME diff -r 849a0b46c767 -r dc41da2f70a4 libraries/iosrv/inc/ioutils.h --- a/libraries/iosrv/inc/ioutils.h Sun Oct 17 18:43:12 2010 +0100 +++ b/libraries/iosrv/inc/ioutils.h Thu Oct 21 22:32:59 2010 +0100 @@ -853,6 +853,7 @@ class RChildProcess { public: + IMPORT_C RChildProcess(); IMPORT_C void Close(); IMPORT_C void CreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr); IMPORT_C void CreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const CEnvironment& aEnv); diff -r 849a0b46c767 -r dc41da2f70a4 tools/fsh-builddocs --- a/tools/fsh-builddocs Sun Oct 17 18:43:12 2010 +0100 +++ b/tools/fsh-builddocs Thu Oct 21 22:32:59 2010 +0100 @@ -420,9 +420,12 @@ } } + my $htmlroot = $pathRelativeToDocRoot; + $htmlroot =~ s/\\/\//g; # HTML link format uses forward slashes + my @args = ("--podpath=.", "--podroot=.", - "--htmlroot=$pathRelativeToDocRoot", + "--htmlroot=$htmlroot", "--recurse", "--infile=$podFileName", "--outfile=$outputFileName");