os/kernelhwsrv/kerneltest/e32test/debug/d_logtofile.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\debug\d_logtofile.cpp
    15 // d_logtofile.ldd is kernel side of t_logtofile application that tests *
    16 // trace handler hook (TTraceHandler). See t_logtofile.cpp for details. *
    17 // 
    18 //
    19 
    20 #include "d_logtofile.h"
    21 #include <kernel/kern_priv.h>
    22 
    23 _LIT(PatternInfo, "Pattern:");
    24 _LIT(BufferInfo, "Buffer Size:");
    25 _LIT(FastCounterInfo, "Fast couner freq:");
    26 const TInt MaxLogSize=300;
    27 ///////////////////////////////////////////////////////////////////////
    28 class DLogToFile : public DLogicalChannelBase
    29 	{
    30 public:
    31 	DLogToFile();
    32 	~DLogToFile();
    33 	static TBool Handler (const TDesC8& aText, TTraceSource aTraceSource);
    34 protected:
    35 	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
    36 	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
    37 private:
    38 	TInt CreateChunk();
    39 	void Start();
    40 	TInt Stop();
    41 	void RemoveChunk();
    42 
    43 private:
    44     DChunk* iChunk;					/**Shared chunk*/
    45     TLinAddr iChunkKernelAddr;		/**Kernel base address of the chunk*/
    46     TUint32 iChunkMapAttr;			/**Mapping attributes of the chunk*/
    47 	TBool iBufferFull;				/**Chunk full indication*/
    48 	TText8* iCurrent;				/**Current pointer to the chunk space*/
    49 	TChunkCreateStr iChunkCreateStr;/**Input arguments(matching pattern and the chunk size) from user side*/
    50 	TTraceHandler iOldHook;			/**Previous trace logging hook*/
    51 	};
    52 
    53 DLogToFile* Logger;
    54 
    55 DLogToFile::DLogToFile() 
    56 	{
    57 	}
    58 
    59 DLogToFile::~DLogToFile()
    60 	{
    61 	Logger = NULL;
    62 	}
    63 
    64 /*
    65 Trace handler hook.
    66 Should be able to run in any content (including ISR).
    67 @return EFalse, always and that way suppresses debug logging to serial port.
    68 */
    69 TBool DLogToFile::Handler (const TDesC8& aText, TTraceSource aTraceSource)
    70 	{
    71 	if(Logger->iBufferFull)
    72 		return ETrue;
    73 
    74 	TInt irq=NKern::DisableAllInterrupts(); //Disable interrupts to prevent loggings overlapping each other.
    75 
    76 	if (aText.Length() < Logger->iChunkCreateStr.iPattern.Length())
    77 		{
    78 		NKern::RestoreInterrupts(irq);
    79 		return ETrue; //The log is too short to match the pattern
    80 		}
    81 	TPtrC8 ptr( aText.Ptr(), Logger->iChunkCreateStr.iPattern.Length());
    82 	if (ptr != Logger->iChunkCreateStr.iPattern) //Compare the pattern against the start of the log
    83 		{
    84 		NKern::RestoreInterrupts(irq);
    85 		return ETrue; //Does not match
    86 		}
    87 
    88 	TBuf8<20> fcBuffer;
    89 	fcBuffer.AppendNum(NKern::FastCounter());//If it was a real tool, we should not do this here.
    90 
    91 	memcpy (Logger->iCurrent, fcBuffer.Ptr(), fcBuffer.Length());
    92 	Logger->iCurrent+=fcBuffer.Length();
    93 	*(Logger->iCurrent++) = '\t';
    94 
    95 	switch(aTraceSource)
    96 		{
    97 		case EKernelTrace:
    98 			{
    99 			*(Logger->iCurrent++) = 'K';
   100 			*(Logger->iCurrent++) = '\t';
   101 			memcpy (Logger->iCurrent, aText.Ptr(),aText.Length());
   102 			break;	
   103 			}
   104 
   105 		case EPlatSecTrace:
   106 			{
   107 			*(Logger->iCurrent++) = 'P';
   108 			*(Logger->iCurrent++) = '\t';
   109 			//PlatSec log could be of any size. Additional checking required:
   110 			if ((TInt)Logger->iCurrent > (TInt)(Logger->iChunkKernelAddr + Logger->iChunkCreateStr.iSize - aText.Length()))
   111 				{
   112 				Logger->iBufferFull = ETrue;
   113 				break;
   114 				}
   115 			memcpy (Logger->iCurrent, aText.Ptr(),aText.Length());
   116 			break;	
   117 			}
   118 		
   119 		case EUserTrace:
   120 			{
   121 			*(Logger->iCurrent++) = 'U';
   122 			*(Logger->iCurrent++) = '\t';
   123 			memcpy(Logger->iCurrent, aText.Ptr(),aText.Length());
   124 			break;	
   125 			}
   126 		
   127 		default:
   128 			break;
   129 		}
   130 
   131 	Logger->iCurrent+=aText.Length();
   132 	*(Logger->iCurrent++) = '\n';
   133 
   134 	if ((TInt)Logger->iCurrent > (TInt)(Logger->iChunkKernelAddr + Logger->iChunkCreateStr.iSize - MaxLogSize))
   135 		Logger->iBufferFull = ETrue;
   136 
   137 	NKern::RestoreInterrupts(irq);
   138 
   139 	return ETrue;
   140 	}
   141 
   142 /**
   143 Creates the channel
   144 */
   145 TInt DLogToFile::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
   146 	{
   147 	return KErrNone;
   148 	}
   149 
   150 /*
   151 Creates chunk and opens another chunk handle for user side.
   152 Returns user side handle.
   153 */
   154 TInt DLogToFile::CreateChunk()
   155 {
   156 	TInt r;
   157     TChunkCreateInfo info;
   158     info.iType         = TChunkCreateInfo::ESharedKernelSingle;
   159     info.iMaxSize      = iChunkCreateStr.iSize;//This is hard coded to 64K. No need to round to page size.
   160 #ifdef __EPOC32__
   161     info.iMapAttr      = (TInt)EMapAttrFullyBlocking; // Full caching
   162 #endif
   163     info.iOwnsMemory   = ETrue; // Use memory from system's free pool
   164     info.iDestroyedDfc = NULL;
   165 
   166 	NKern::ThreadEnterCS();
   167     if (KErrNone != (r = Kern::ChunkCreate(info, iChunk, iChunkKernelAddr, iChunkMapAttr)))
   168 		{
   169 		NKern::ThreadLeaveCS();
   170 		return r;
   171 		}
   172 	r = Kern::ChunkCommit(iChunk,0,iChunkCreateStr.iSize);
   173     if(r!=KErrNone)
   174         {
   175 		Kern::ChunkClose(iChunk);
   176 		NKern::ThreadLeaveCS();
   177 		return r;
   178 		}
   179 	r = Kern::MakeHandleAndOpen(NULL, iChunk); 
   180     if(r < KErrNone)
   181         {
   182 		Kern::ChunkClose(iChunk);
   183 		NKern::ThreadLeaveCS();
   184 		return r;
   185 		}
   186 	NKern::ThreadLeaveCS();
   187 	iCurrent = (TText8*)iChunkKernelAddr;
   188 	return r;
   189 }
   190 
   191 
   192 /*
   193 Logs input parameters info into chunk and starts logging.
   194 */
   195 void DLogToFile::Start()
   196 	{
   197 	//Log pattern info
   198 	memcpy (Logger->iCurrent, ((const TDesC&)PatternInfo).Ptr(), ((const TDesC&)PatternInfo).Length());
   199 	iCurrent+=((const TDesC&)PatternInfo).Length();
   200 	*(Logger->iCurrent++) = '\t';
   201 	memcpy (Logger->iCurrent, iChunkCreateStr.iPattern.Ptr(), iChunkCreateStr.iPattern.Length());
   202 	Logger->iCurrent += iChunkCreateStr.iPattern.Length();
   203 	*(iCurrent++) = '\n';
   204 
   205 	//Log buffern info
   206 	memcpy (iCurrent, ((const TDesC&)BufferInfo).Ptr(), ((const TDesC&)BufferInfo).Length());
   207 	iCurrent+=((const TDesC&)BufferInfo).Length();
   208 	*(Logger->iCurrent++) = '\t';
   209 	TBuf8<20> buf;
   210 	buf.AppendNum(iChunkCreateStr.iSize);
   211 	memcpy (iCurrent, buf.Ptr(), buf.Length());
   212 	iCurrent+=buf.Length();
   213 	*(iCurrent++) = '\n';
   214 
   215 	//Log fast counter info
   216 	memcpy (iCurrent, ((const TDesC&)FastCounterInfo).Ptr(), ((const TDesC&)FastCounterInfo).Length());
   217 	iCurrent+=((const TDesC&)FastCounterInfo).Length();
   218 	*(iCurrent++) = '\t';
   219 	buf.SetLength(0);
   220 	buf.AppendNum(NKern::FastCounterFrequency());
   221 	memcpy (iCurrent, buf.Ptr(), buf.Length());
   222 	iCurrent+=buf.Length();
   223 	*(iCurrent++) = '\n';
   224 
   225 	//Start logging	
   226 	iOldHook = Kern::SetTraceHandler(DLogToFile::Handler);
   227 	}
   228 
   229 /*
   230 Stops logging into chunk. Returns the size of the log.
   231 */
   232 TInt DLogToFile::Stop()
   233 	{
   234 	//Setting the old hook is always risky. Is the old hook still valid?
   235 	//We'll do it for the sake of testing.
   236 	Kern::SetTraceHandler(iOldHook);
   237 	return (TInt)Logger->iCurrent  - Logger->iChunkKernelAddr;
   238 	}
   239 
   240 /*
   241 Closes the shared chunk
   242 */
   243 void DLogToFile::RemoveChunk()
   244 {
   245 	NKern::ThreadEnterCS();
   246 	//It has been a while since we removed the hook. It should be safe to close the chunk now. 
   247 	Kern::ChunkClose(iChunk);
   248 	NKern::ThreadLeaveCS();
   249 }
   250 
   251 /**
   252 User side request entry point.
   253 */
   254 TInt DLogToFile::Request(TInt aFunction, TAny* a1, TAny* /*a2*/)
   255 	{
   256 	TInt r = KErrNone;
   257 	switch (aFunction)
   258 	{
   259 		case RLogToFileDevice::EControlCreateChunk:
   260 			{
   261 			kumemget(&iChunkCreateStr, a1,sizeof(TChunkCreateStr));
   262 			r = CreateChunk();
   263 			break;
   264 			}
   265 		case RLogToFileDevice::EControlStart:
   266 			{
   267 			Start();
   268 			break;
   269 			}
   270 		case RLogToFileDevice::EControlStop:
   271 			{
   272 			r = Stop();
   273 			break;
   274 			}
   275 		case RLogToFileDevice::EControlRemoveChunk:
   276 			{
   277 			RemoveChunk();
   278 			break;
   279 			}
   280 		default:
   281 			r=KErrNotSupported;
   282 			break;
   283 		}
   284 	return r;
   285 	}
   286 
   287 //////////////////////////////////////////
   288 class DTestFactory : public DLogicalDevice
   289 	{
   290 public:
   291 	DTestFactory();
   292 	// from DLogicalDevice
   293 	virtual TInt Install();
   294 	virtual void GetCaps(TDes8& aDes) const;
   295 	virtual TInt Create(DLogicalChannelBase*& aChannel);
   296 	};
   297 
   298 DTestFactory::DTestFactory()
   299     {
   300     iParseMask = KDeviceAllowUnit;
   301     iUnitsMask = 0x3;
   302     }
   303 
   304 TInt DTestFactory::Create(DLogicalChannelBase*& aChannel)
   305     {
   306 	Logger = new DLogToFile;
   307 	aChannel = Logger;
   308 	return (aChannel ? KErrNone : KErrNoMemory);
   309     }
   310 
   311 TInt DTestFactory::Install()
   312     {
   313     return SetName(&KLogToFileName);
   314     }
   315 
   316 void DTestFactory::GetCaps(TDes8& /*aDes*/) const
   317     {
   318     }
   319 
   320 DECLARE_STANDARD_LDD()
   321 	{
   322     return new DTestFactory;
   323 	}