kernel/eka/kernel/smonitor.cpp
changeset 0 a41df078684a
child 43 c1f20ce4abcf
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1994-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 // e32\kernel\smonitor.cpp
       
    15 // Kernel crash debugger - machine independent portion common between the crash
       
    16 // debugger and crash logger.
       
    17 // 
       
    18 //
       
    19 
       
    20 #include <kernel/monitor.h>
       
    21 #include "msgqueue.h"
       
    22 
       
    23 #define iMState		iWaitLink.iSpare1
       
    24 
       
    25 GLDEF_D Monitor* TheMonitorPtr = 0;
       
    26 LOCAL_D Monitor* TheAltMonitorPtrs[MONITOR_MAXCOUNT] = { 0 };
       
    27 
       
    28 _LIT8(KLitThread, "THREAD");
       
    29 _LIT8(KLitProcess, "PROCESS");
       
    30 _LIT8(KLitChunk, "CHUNK");
       
    31 _LIT8(KLitLibrary, "LIBRARY");
       
    32 _LIT8(KLitSemaphore, "SEMAPHORE");
       
    33 _LIT8(KLitMutex, "MUTEX");
       
    34 _LIT8(KLitTimer, "TIMER");
       
    35 _LIT8(KLitServer, "SERVER");
       
    36 _LIT8(KLitSession, "SESSION");
       
    37 _LIT8(KLitLogicalDevice, "LOGICAL DEVICE");
       
    38 _LIT8(KLitPhysicalDevice, "PHYSICAL DEVICE");
       
    39 _LIT8(KLitLogicalChannel, "LOGICAL CHANNEL");
       
    40 _LIT8(KLitChangeNotifier, "CHANGE NOTIFIER");
       
    41 _LIT8(KLitUndertaker, "UNDERTAKER");
       
    42 _LIT8(KLitUnknown, "UNKNOWN");
       
    43 _LIT8(KLitLibraries, "LIBRARIES");
       
    44 _LIT8(KLitS, "S");
       
    45 _LIT8(KLitES, "ES");
       
    46 _LIT8(KLitMsgQueue, "MESSAGE QUEUE");
       
    47 _LIT8(KLitPropertyRef, "PROPERTY REF");
       
    48 _LIT8(KLitCondVar, "CONDITION VARIABLE");
       
    49 
       
    50 const TDesC8* const ContainerName[ENumObjectTypes]=
       
    51 	{
       
    52 	&KLitThread,
       
    53 	&KLitProcess,
       
    54 	&KLitChunk,
       
    55 	&KLitLibrary,
       
    56 	&KLitSemaphore,
       
    57 	&KLitMutex,
       
    58 	&KLitTimer,
       
    59 	&KLitServer,
       
    60 	&KLitSession,
       
    61 	&KLitLogicalDevice,
       
    62 	&KLitPhysicalDevice,
       
    63 	&KLitLogicalChannel,
       
    64 	&KLitChangeNotifier,
       
    65 	&KLitUndertaker,
       
    66 	&KLitMsgQueue,
       
    67 	&KLitPropertyRef,
       
    68 	&KLitCondVar
       
    69 	};
       
    70 
       
    71 void mstrcat(TDes8& aDes, const char* s)
       
    72 	{
       
    73 	aDes+=TPtrC8((const TUint8*)s);
       
    74 	}
       
    75 
       
    76 void Monitor::GetObjectTypeName(TDes8& aDes, TInt aType, TBool aPlural)
       
    77 	{
       
    78 	if (aType<0 || aType>=ENumObjectTypes)
       
    79 		aDes=KLitUnknown;
       
    80 	else
       
    81 		{
       
    82 		aDes=*ContainerName[aType];
       
    83 		if (aPlural)
       
    84 			{
       
    85 			switch (aType)
       
    86 				{
       
    87 				case EProcess:
       
    88 				case EMutex:
       
    89 					aDes+=KLitES;
       
    90 					break;
       
    91 				case ELibrary:
       
    92 					aDes=KLitLibraries;
       
    93 					break;
       
    94 				default:
       
    95 					aDes+=KLitS;
       
    96 					break;
       
    97 				}
       
    98 			}
       
    99 		}
       
   100 	}
       
   101 
       
   102 EXPORT_C void Monitor::PrintLine(const TDesC8& aDes)
       
   103 	{
       
   104 	Print(aDes);
       
   105 	NewLine();
       
   106 	}
       
   107 
       
   108 EXPORT_C void Monitor::Printf(const char* aFmt, ...)
       
   109 	{
       
   110 	TBuf8<256> printBuf;
       
   111 	VA_LIST list;
       
   112 	VA_START(list,aFmt);
       
   113 	Kern::AppendFormat(printBuf,aFmt,list);
       
   114 	Print(printBuf);
       
   115 	}
       
   116 
       
   117 EXPORT_C void Monitor::Print(const char* s)
       
   118 	{
       
   119 	Print(TPtrC8((const TUint8*)s));
       
   120 	}
       
   121 
       
   122 EXPORT_C void Monitor::PrintLine(const char* s)
       
   123 	{
       
   124 	Print(s);
       
   125 	NewLine();
       
   126 	}
       
   127 
       
   128 EXPORT_C void Monitor::NewLine()
       
   129 	{
       
   130 	TBuf<2> buf(0);
       
   131 	buf.Append(0x0d);
       
   132 	buf.Append(0x0a);
       
   133 	Print(buf);
       
   134 	}
       
   135 
       
   136 DMonObject* DMonObject::Owner()
       
   137 	{
       
   138 	if (iOwner)
       
   139 		return iOwner;
       
   140 	return NULL;
       
   141 	}
       
   142 
       
   143 TInt DMonObject::Type()
       
   144 	{
       
   145 	return iContainerID-1;  // KErrNotFound (-1) returned for objects not in a container
       
   146 	}
       
   147 
       
   148 void DMonObject::AppendName(TDes8& aDes)
       
   149 	{
       
   150 	((DObject*)this)->TraceAppendName(aDes,EFalse);
       
   151 	}
       
   152 
       
   153 void DMonObject::FullName(TDes8& aDes)
       
   154 	{
       
   155 	((DObject*)this)->TraceAppendFullName(aDes,EFalse);
       
   156 	}
       
   157 
       
   158 EXPORT_C void Monitor::ObjectDump(TUint aAddr)
       
   159 	{
       
   160 	DMonObject* pO=(DMonObject*)aAddr;
       
   161 	pO->DumpData();
       
   162 	}
       
   163 
       
   164 EXPORT_C void Monitor::ObjectFullDump(TUint aAddr)
       
   165 	{
       
   166 	DMonObject* pO=(DMonObject*)aAddr;
       
   167 	TInt index=pO->Type();
       
   168 	DumpObjectData(pO,index);
       
   169 	}
       
   170 
       
   171 EXPORT_C void Monitor::DoMemoryDumpL(TUint aStart, TInt aLength)
       
   172 	{
       
   173 	TUint readSize=0x1;
       
   174 	DoMemoryDumpL(aStart,aLength,readSize);		
       
   175 	}
       
   176 
       
   177  
       
   178  EXPORT_C void Monitor::DoMemoryDumpL(TUint aStart, TInt aLength, TUint aReadSize)
       
   179  	{
       
   180     TBuf8<80> out;
       
   181 	TBuf8<20> ascii;
       
   182 	TUint a=aStart;
       
   183 	do
       
   184 		{
       
   185 		out.Zero();
       
   186 		ascii.Zero();
       
   187 		out.AppendNumFixedWidth(a,EHex,8);
       
   188 		out.Append(_L(": "));
       
   189 		TUint b;
       
   190 		if(aReadSize == 0x4)
       
   191 	   		{
       
   192 			for (b=0; b<16; b=b+4)
       
   193 				{
       
   194 				TUint c=*(TUint*)(a+b);
       
   195 				out.AppendNumFixedWidth(c,EHex,8);
       
   196 				out.Append(' ');
       
   197 				if (c<0x20 || c>=0x7f)
       
   198 					{
       
   199 					c=0x2e;
       
   200 					}
       
   201 				ascii.Append(TChar(c));
       
   202 				}
       
   203 			}	
       
   204 		else if(aReadSize == 0x2)
       
   205 			{
       
   206 			for (b=0; b<16; b+=2)
       
   207 				{
       
   208 				TUint16 c=*(TUint16*)(a+b);
       
   209 				out.AppendNumFixedWidth(c,EHex,4);
       
   210 				out.Append(' ');
       
   211 				if (c<0x20 || c>=0x7f)
       
   212 					{
       
   213 					c=0x2e;	
       
   214 					}
       
   215 				ascii.Append(TChar(c));
       
   216 				}	
       
   217 			}
       
   218 		else if(aReadSize == 0x1)
       
   219 			{
       
   220 			for (b=0; b<16; b++)
       
   221 				{
       
   222 				TUint8 c=*(TUint8*)(a+b);
       
   223 				out.AppendNumFixedWidth(c,EHex,2);
       
   224 				out.Append(' ');
       
   225 				if (c<0x20 || c>=0x7f)
       
   226 					{
       
   227 					c=0x2e;	
       
   228 					}
       
   229 				ascii.Append(TChar(c));
       
   230 				}
       
   231 			}
       
   232 		out.Append(ascii);
       
   233 		PrintLine(out);
       
   234 		a+=16;
       
   235 		aLength-=16;
       
   236 		}while(aLength>0); 
       
   237  	}
       
   238 
       
   239 LOCAL_C TUint32 Read32L(TUint32 anAddr)
       
   240 	{
       
   241 	return *((TUint32*)anAddr);
       
   242 	}
       
   243 
       
   244 EXPORT_C void Monitor::DoDiscontiguousMemoryDumpL(TUint aStart, TInt aLength)
       
   245 	{
       
   246 	TUint readSize=0x1;
       
   247 	DoDiscontiguousMemoryDumpL(aStart, aLength, readSize);
       
   248 	}
       
   249 
       
   250 
       
   251 EXPORT_C void Monitor::DoDiscontiguousMemoryDumpL(TUint aStart, TInt aLength, TUint aReadSize)
       
   252 	{
       
   253 	const TUint KPageMask = iPageSize - 1;
       
   254 
       
   255 	TUint start = aStart & ~0xf; // start and finish on 16-byte boundary
       
   256 	TUint limit = (aStart + aLength + 0xf) & ~0xf;
       
   257 	while(start!=limit)
       
   258 		{
       
   259 		MTRAPD(r,DoMemoryDumpL(start,limit-start,aReadSize));
       
   260 		if (r==KErrNone)
       
   261 			return;
       
   262 		if (r!=KErrAbort)
       
   263 			Leave(r);
       
   264 
       
   265 		// Got page fault so keep attempting to read from the next page until a valid 
       
   266 		// page is found or the limit is reached.
       
   267 		start = iExceptionInfo[1];	// faulted address
       
   268 		TUint exceptionStart = start;
       
   269 		do
       
   270 			{
       
   271 			ProcessError(r); // Output the fault information.
       
   272 			start = (start + iPageSize) & ~KPageMask; // move on to next page
       
   273 			if (TUint(start-limit) <= TUint(iPageSize))
       
   274 				{ // reached limit
       
   275 				start = limit;
       
   276 				break;
       
   277 				}
       
   278 			MTRAP(r,Read32L(start));
       
   279 			}
       
   280 		while (r!=KErrNone);
       
   281 
       
   282 		Printf("Skipped %x bytes due to exception(s)\r\n", start - exceptionStart);
       
   283 		NewLine();
       
   284 		}
       
   285 	}
       
   286 
       
   287 void DMonObject::DumpData()
       
   288 	{
       
   289 	TBuf8<32> f;
       
   290 	Monitor::GetObjectTypeName(f,Type(),EFalse);
       
   291 	TheMonitorPtr->Printf("%S at %08x VPTR=%08x AccessCount=%d Owner=%08x\r\n",&f,this,iVptr,iAccessCount,iOwner);
       
   292 	TBuf8<KMaxKernelName> object_name;
       
   293 	FullName(object_name);
       
   294 	TheMonitorPtr->Printf("Full name %S\r\n",&object_name);	
       
   295 	}
       
   296 
       
   297 EXPORT_C void Monitor::DisplayFaultInfo()
       
   298 	{
       
   299 	TSuperPage& sp=Kern::SuperPage();
       
   300 	TExcInfo& x=sp.iKernelExcInfo;
       
   301 	Printf("Fault Category: %S  Fault Reason: %08x\r\n",&iFaultCategory,iFaultReason);
       
   302 	Printf("ExcId %08x CodeAddr %08x DataAddr %08x Extra %08x\r\n",sp.iKernelExcId,x.iCodeAddress,x.iDataAddress,x.iExtraData);
       
   303 	DisplayCpuFaultInfo();
       
   304 	}
       
   305 
       
   306 void Monitor::DumpThreadData(DThread* pT)
       
   307 	{
       
   308 	TBuf8<80> buf=_L8("Thread MState ");
       
   309 	switch(pT->iMState)
       
   310 		{
       
   311 		case DThread::ECreated: buf+=_L8("CREATED"); break;
       
   312 		case DThread::EDead: buf+=_L8("DEAD"); break;
       
   313 		case DThread::EReady: buf+=_L8("READY"); break;
       
   314 		case DThread::EWaitSemaphore: buf+=_L8("WAITSEM "); buf.AppendNumFixedWidth((TUint)pT->iWaitObj,EHex,8); break;
       
   315 		case DThread::EWaitSemaphoreSuspended: buf+=_L8("WAITSEMS "); buf.AppendNumFixedWidth((TUint)pT->iWaitObj,EHex,8); break;
       
   316 		case DThread::EWaitMutex: buf+=_L8("WAITMUTEX "); buf.AppendNumFixedWidth((TUint)pT->iWaitObj,EHex,8); break;
       
   317 		case DThread::EWaitMutexSuspended: buf+=_L8("WAITMUTXS "); buf.AppendNumFixedWidth((TUint)pT->iWaitObj,EHex,8); break;
       
   318 		case DThread::EHoldMutexPending: buf+=_L8("HOLDMUTXP "); buf.AppendNumFixedWidth((TUint)pT->iWaitObj,EHex,8); break;
       
   319 		case DThread::EWaitCondVar: buf+=_L8("WAITCONDVAR "); buf.AppendNumFixedWidth((TUint)pT->iWaitObj,EHex,8); break;
       
   320 		case DThread::EWaitCondVarSuspended: buf+=_L8("WAITCONDVRS "); buf.AppendNumFixedWidth((TUint)pT->iWaitObj,EHex,8); break;
       
   321 		default: buf+=_L8("??"); buf.AppendNumFixedWidth((TUint)pT->iMState,EHex,8); break;
       
   322 		}
       
   323 	PrintLine(buf);
       
   324 	Printf("Default priority %d WaitLink Priority %d\r\n",pT->iDefaultPriority,pT->iWaitLink.iPriority);
       
   325 	Printf("ExitInfo %d,%d,%lS\r\n",pT->iExitType,pT->iExitReason,&pT->iExitCategory);
       
   326 	Printf("Flags %08x, Handles %08x\r\n",pT->iFlags,&pT->iHandles);
       
   327 	Printf("Supervisor stack base %08x size %x\r\n", pT->iSupervisorStack, pT->iSupervisorStackSize);
       
   328 	Printf("User stack base %08x size %x\r\n", pT->iUserStackRunAddress, pT->iUserStackSize);
       
   329 	Printf("Id=%d, Alctr=%08x, Created alctr=%08x, Frame=%08x\r\n",pT->iId,pT->iAllocator,pT->iCreatedAllocator,pT->iFrame);
       
   330 	Printf("Trap handler=%08x, ActiveScheduler=%08x, Exception handler=%08x\r\n",
       
   331 								pT->iTrapHandler, pT->iScheduler, pT->iExceptionHandler);
       
   332 	Printf("TempObj=%08x TempAlloc=%08x IpcCount=%08x\r\n",pT->iTempObj,pT->iTempAlloc,pT->iIpcCount);
       
   333 	DisplayNThreadInfo(&pT->iNThread);
       
   334 	DumpCpuThreadData(pT);
       
   335 	}
       
   336 
       
   337 
       
   338 void Monitor::DoStackDumpL(TUint aStart, TUint aEnd)
       
   339 	{
       
   340 	const TUint KPageMask = iPageSize - 1;
       
   341 
       
   342  	// Skip unused area of stack to minimise size of dump
       
   343 	aStart &= 0xfffffff0;
       
   344 	TUint* ptr = (TUint*)aStart;
       
   345   	TUint* limit = (TUint*)aEnd;
       
   346   	TUint pattern = 0;
       
   347 	TUint* abortAddr = 0;
       
   348 	while (ptr < limit)
       
   349 		{
       
   350 		MTRAPD(r, pattern = *ptr);
       
   351 		if(r == KErrNone)
       
   352 			break;
       
   353 		// Current page not found so move onto the next one.
       
   354 		ptr = (TUint*)(((TUint)ptr + iPageSize) & ~KPageMask);
       
   355 		abortAddr = ptr;
       
   356 		ProcessError(r);
       
   357 		}
       
   358 
       
   359   	if (pattern == 0x29292929 ||	// User stack
       
   360 		pattern == 0xeeeeeeee ||	// Supervisor stack
       
   361 		pattern == 0xffffffff || 
       
   362 		pattern == 0xaaaaaaaa ||	// IRQ stack
       
   363 		pattern == 0xbbbbbbbb ||	// FIQ stack
       
   364 		pattern == 0xdddddddd ||	// ABT and UND stack
       
   365 		pattern == 0x03030303)		// Uninitialised memory
       
   366   		{
       
   367   		while ((ptr + 3) < limit)
       
   368 			{
       
   369   			MTRAPD(r, if( ptr[0] == pattern && ptr[1] == pattern && ptr[2] == pattern && ptr[3] == pattern) ptr+=4; else break;);
       
   370 			if (r != KErrNone)
       
   371 				{// Current page not found so move onto the next one.
       
   372 				ptr = (TUint*)(((TUint)ptr + iPageSize) & ~KPageMask);
       
   373 				abortAddr = ptr;	// Due to alignment ptr[0]-ptr[3] will all be within the same page.
       
   374 				ProcessError(r);
       
   375 				}
       
   376 			}
       
   377   		}
       
   378   	if (ptr != (TUint*)aStart)
       
   379 		{
       
   380 		if (abortAddr)
       
   381 			{
       
   382 			Printf("Skipped %x bytes due to exception(s)\r\n", (TUint)abortAddr - aStart);
       
   383 			if (ptr != abortAddr)
       
   384 				Printf("Skipped %x unused bytes of %02x\r\n", (TUint)ptr - (TUint)abortAddr, pattern & 0xff);
       
   385 			}
       
   386 		else
       
   387 			{
       
   388 			Printf("Skipped %x unused bytes of %02x\r\n", (TUint)ptr - aStart, pattern & 0xff);
       
   389 			}
       
   390 		}
       
   391 
       
   392 	if (ptr < limit)
       
   393 		DoDiscontiguousMemoryDumpL((TUint)ptr, (limit - ptr) << 2, (TBool)ETrue);
       
   394   	}
       
   395 
       
   396 void Monitor::DoDumpThreadStack(DThread *aThread)
       
   397 	{
       
   398 	DMonObject* pO=(DMonObject*)aThread;
       
   399 	if (!pO || pO->Type()!=EThread)
       
   400 		{
       
   401 		return;
       
   402 		}
       
   403 	pO->DumpData();
       
   404 
       
   405 	TUint supSp, usrSp;
       
   406 	GetStackPointers(&aThread->iNThread, supSp, usrSp);
       
   407 	
       
   408 	if (aThread->iUserStackRunAddress && aThread->iUserStackSize)
       
   409 		{
       
   410 		TInt usrSize = aThread->iUserStackSize;
       
   411 		TUint usrRunStart = (TUint)aThread->iUserStackRunAddress;
       
   412 		TUint usrRunEnd = usrRunStart+usrSize;
       
   413 		
       
   414 		Printf("User stack base at %08x, size == %x\r\n", usrRunStart, usrSize);
       
   415 		Printf("Stack pointer == %08x\r\n", usrSp);
       
   416 
       
   417 		TUint usrStart = MapAndLocateUserStack(aThread);
       
   418 		if (usrStart)
       
   419 			{
       
   420 			Printf("Stack mapped at %08x\r\n", usrStart);
       
   421 
       
   422 			TUint usrEnd = usrStart + usrSize;
       
   423 			if (usrSp >= usrRunStart && usrSp < usrRunEnd)
       
   424 				usrStart += usrSp - usrRunStart;
       
   425 			
       
   426 			DoStackDumpL(usrStart, usrEnd);
       
   427 			NewLine();
       
   428 			}
       
   429 		else
       
   430 			Printf("Couldn't locate user stack\r\n");
       
   431 		}
       
   432 	else
       
   433 		Printf("No user-mode stack\r\n");
       
   434 
       
   435 	TInt  supSize = aThread->iSupervisorStackSize;
       
   436 	TUint supStart = (TUint)aThread->iSupervisorStack;
       
   437 	TUint supEnd = supStart+supSize;
       
   438 	
       
   439 	Printf("Supervisor stack base at %08x, size == %x\r\n", supStart, supSize);
       
   440 	Printf("Stack pointer == %08x\r\n", supSp);	
       
   441 	
       
   442 	if (supSp >= supStart && supSp < supEnd)
       
   443 		supStart = supSp;
       
   444  
       
   445 	DoStackDumpL(supStart, supEnd);
       
   446 	}
       
   447 
       
   448 EXPORT_C void Monitor::DumpThreadStack(DThread *aThread)
       
   449 	{
       
   450 	MTRAPD(r,DoDumpThreadStack(aThread));
       
   451 	if (r!=KErrNone)
       
   452 		ProcessError(r);
       
   453 	}
       
   454 
       
   455 EXPORT_C void Monitor::DumpThreadStacks(TBool aIncludeCurrent)
       
   456 	{
       
   457 	DObjectCon* pC=Container(EThread);
       
   458 	for (TInt i=0 ; i<pC->Count() ; ++i)
       
   459 		{
       
   460 		DThread* pT=(DThread*)(*pC)[i];
       
   461 		if (aIncludeCurrent || pT!=&Kern::CurrentThread())
       
   462 			{
       
   463 			DumpThreadStack(pT);
       
   464 			NewLine();
       
   465 			}
       
   466 		}
       
   467 	}
       
   468 	
       
   469 
       
   470 EXPORT_C void Monitor::DumpExceptionStacks()
       
   471 	{
       
   472  	#if defined(__EPOC32__) && !defined(__CPU_X86)
       
   473  
       
   474  	TStackInfo& stackInfo = Kern::SuperPage().iStackInfo;
       
   475  
       
   476 	Printf("IRQ stack base at %08x, size == %x\r\n", stackInfo.iIrqStackBase, stackInfo.iIrqStackSize);
       
   477  	MTRAPD(r1,DoStackDumpL((TLinAddr)stackInfo.iIrqStackBase,
       
   478 						   (TLinAddr)stackInfo.iIrqStackBase + stackInfo.iIrqStackSize));
       
   479  	if(r1!=KErrNone)
       
   480  		ProcessError(r1);
       
   481  		
       
   482 	Printf("\r\nFIQ stack base at %08x, size == %x\r\n", stackInfo.iFiqStackBase, stackInfo.iFiqStackSize);
       
   483  	MTRAPD(r2,DoStackDumpL((TLinAddr)stackInfo.iFiqStackBase,
       
   484 						   (TLinAddr)stackInfo.iFiqStackBase + stackInfo.iFiqStackSize));
       
   485  	if(r2!=KErrNone)
       
   486  		ProcessError(r2);	
       
   487  
       
   488  	#else
       
   489 	PrintLine("Not Supported");
       
   490  	#endif
       
   491  	}
       
   492  	
       
   493  
       
   494 void Monitor::DumpProcessData(DProcess* pP)
       
   495 	{
       
   496 	Printf("ExitInfo %d,%d,%lS\r\n",pP->iExitType,pP->iExitReason,&pP->iExitCategory);
       
   497 	Printf("Flags %08x, Handles %08x, Attributes %08x\r\n",pP->iFlags,&pP->iHandles,pP->iAttributes);
       
   498 	Printf("DataBssChunk %08x, CodeSeg %08x\r\n",pP->iDataBssStackChunk,pP->iCodeSeg);
       
   499 	Printf("DllLock %08x, Process Lock %08x SID %08x\r\n",pP->iDllLock,pP->iProcessLock,pP->iS.iSecureId);
       
   500 	Printf("TempCodeSeg %08x CodeSeg %08x Capability %08x %08x\r\n",pP->iTempCodeSeg,pP->iCodeSeg,pP->iS.iCaps[1],pP->iS.iCaps[0]);
       
   501 	TInt c=pP->iDynamicCode.Count();
       
   502 	Printf("CodeSegs: Count=%d\r\n",c);
       
   503 	if (c>0)
       
   504 		{
       
   505 		SCodeSegEntry* e = &pP->iDynamicCode[0];
       
   506 		TInt i;
       
   507 		for(i=0; i<c; ++i, ++e)
       
   508 			Printf("%2d: seg=%08x lib=%08x\r\n", i, e->iSeg, e->iLib);
       
   509 		}
       
   510 	DumpMemModelProcessData(pP);
       
   511 	DumpCpuProcessData(pP);
       
   512 	}
       
   513 
       
   514 void Monitor::DumpMessageQueueData(DMsgQueue* aQueue)
       
   515 	{
       
   516 	Printf("StartOfPool %08x, EndOfPool %08x\r\n", aQueue->iMsgPool, aQueue->iEndOfPool);
       
   517 	Printf("FirstFullSlot %08x, FirstFreeSlot %08x\r\n", aQueue->iFirstFullSlot, aQueue->iFirstFreeSlot);
       
   518 	Printf("MaxMsgLength %d\r\n", aQueue->iMaxMsgLength);
       
   519 	TBuf8<80> buf=_L8("MessageQueue state ");
       
   520 	switch (aQueue->iState)
       
   521 		{
       
   522 		case DMsgQueue::EEmpty: buf+=_L8("Empty"); break;
       
   523 		case DMsgQueue::EPartial: buf+=_L8("Partial"); break;
       
   524 		case DMsgQueue::EFull: buf+=_L8("Full"); break;
       
   525 		default: buf+=_L8("????"); break;
       
   526 		}
       
   527 	PrintLine(buf);
       
   528 	Printf("ThreadWaitingForData %08x, DataAvailStatPtr %08x\r\n", 
       
   529 		   aQueue->iThreadWaitingOnDataAvail, aQueue->iDataAvailRequest->StatusPtr());
       
   530 	Printf("ThreadWaitingForSpace %08x, SpaceAvailStatPtr %08x\r\n", 
       
   531 		   aQueue->iThreadWaitingOnSpaceAvail, aQueue->iSpaceAvailRequest->StatusPtr());
       
   532 	}
       
   533 
       
   534 
       
   535 void Monitor::DumpObjectData(DMonObject* pO, TInt type)
       
   536 	{
       
   537 	if (!pO)
       
   538 		return;
       
   539 	pO->DumpData();
       
   540 	switch(type)
       
   541 		{
       
   542 		case EThread: DumpThreadData((DThread*)pO); break;
       
   543 		case EProcess: DumpProcessData((DProcess*)pO); break;
       
   544 		case EChunk: DumpChunkData((DChunk*)pO); break;
       
   545 		case ELibrary: break;
       
   546 		case ESemaphore: break;
       
   547 		case EMutex: break;
       
   548 		case ETimer: break;
       
   549 		case EServer: break;
       
   550 		case ESession: break;
       
   551 		case ELogicalDevice: break;
       
   552 		case EPhysicalDevice: break;
       
   553 		case ELogicalChannel: break;
       
   554 		case EChangeNotifier: break;
       
   555 		case EUndertaker: break;
       
   556 		case EMsgQueue: DumpMessageQueueData((DMsgQueue*)pO); break;
       
   557 		case EPropertyRef: break;
       
   558 		case ECondVar: break;
       
   559 		default: break;
       
   560 		}
       
   561 	}
       
   562 
       
   563 
       
   564 DObjectCon* Monitor::Container(TInt anIndex)
       
   565 	{
       
   566 	return Kern::Containers()[anIndex];
       
   567 	}
       
   568 
       
   569 EXPORT_C void Monitor::DumpObjectContainer(TUint aIndex, TBool aPause)
       
   570 	{
       
   571 	if(aIndex>=ENumObjectTypes)
       
   572 		{
       
   573 		PrintLine(_L8("Invalid object type"));
       
   574 		return;
       
   575 		}
       
   576 	DObjectCon* pC=Container(aIndex);
       
   577 	TInt c=pC->Count();
       
   578 	TBuf8<32> type;
       
   579 	GetObjectTypeName(type, aIndex, c!=1);
       
   580 	Printf("Container %d at %08x contains %d %S:\r\n",aIndex,pC,c,&type);
       
   581 	TInt j;
       
   582 	for (j=0; j<c; j++)
       
   583 		{
       
   584 		DObject* pO=(*pC)[j];
       
   585 		Monitor::DumpObjectData((DMonObject*)pO,aIndex);
       
   586 		Pause(aPause);
       
   587 		}
       
   588 	NewLine();
       
   589 	}
       
   590 		
       
   591 void Monitor::DisplayDebugMaskInfo()
       
   592 	{
       
   593     for(TInt index=0; index<KNumTraceMaskWords; index++)
       
   594     	{
       
   595     	Printf("DebugMask[%d] = %08x\r\n", index, Kern::SuperPage().iDebugMask[index]);
       
   596     	}
       
   597      }
       
   598 
       
   599 EXPORT_C void Monitor::Pause(TBool aPause)
       
   600 	{
       
   601 	}
       
   602 
       
   603 EXPORT_C void Monitor::ProcessInfoCommand(const TDesC8& aDes, TInt& i)
       
   604 	{
       
   605 	DisplaySchedulerInfo();
       
   606 	DisplayDebugMaskInfo();
       
   607 	NThread* currentThread = NKern::CurrentThread();
       
   608 	DMonObject* pO=(DMonObject*)Kern::NThreadToDThread(currentThread);
       
   609 	if (pO)
       
   610 		{
       
   611 		Printf("TheCurrentThread=%08x\r\n",pO);
       
   612 		Monitor::DumpObjectData(pO,EThread);
       
   613 		pO=(DMonObject*)&Kern::CurrentProcess();
       
   614 		Printf("TheCurrentProcess=%08x\r\n",pO);
       
   615 		Monitor::DumpObjectData(pO,EProcess);
       
   616 		MMProcessInfoCommand();
       
   617 		}
       
   618 	else
       
   619 		Printf("NCurrentThread=%08x\r\nNThread has no DProcess\r\n",currentThread);
       
   620 
       
   621 	}
       
   622 
       
   623 EXPORT_C void Monitor::ProcessError(TInt anError)
       
   624 	{
       
   625 	NewLine();
       
   626 	if (anError==KErrAbort)
       
   627 		{
       
   628 		Printf("Exception: Type %d Code %08x Data %08x Extra %08x\r\n",
       
   629 						iExceptionInfo[3],iExceptionInfo[0],iExceptionInfo[1],iExceptionInfo[2]);
       
   630 		}
       
   631 	else if (anError==KErrCancel)
       
   632 		Print("Escape\r\n");
       
   633 	}
       
   634 
       
   635 EXPORT_C Monitor::Monitor()
       
   636 	{
       
   637 	}
       
   638 
       
   639 void Monitor::Init(TAny* aCategory, TInt aReason)
       
   640 	{
       
   641 	__KTRACE_OPT(KDEBUGGER,Kern::Printf("Calling Monitor 1: %x",TheMonitorPtr));
       
   642 	TInt restartType = TheMonitorPtr->Init2(aCategory,aReason);
       
   643 	
       
   644 	for (TInt i = 0; i < MONITOR_MAXCOUNT && TheAltMonitorPtrs[i]; ++i)
       
   645 		{
       
   646 		//Initialise data members of the Alternative Monitor (see Monitor::Entry)
       
   647 		TheAltMonitorPtrs[i]->iRegs = TheMonitorPtr->iRegs;
       
   648 		TheAltMonitorPtrs[i]->iPageSize = TheMonitorPtr->iPageSize;
       
   649 
       
   650 		TheMonitorPtr = TheAltMonitorPtrs[i];
       
   651 		__KTRACE_OPT(KDEBUGGER,Kern::Printf("Calling Monitor %d: %x",i+2,TheMonitorPtr));
       
   652 		restartType |= TheMonitorPtr->Init2(aCategory,aReason);
       
   653 		}
       
   654 
       
   655 	__KTRACE_OPT(KALWAYS,Kern::Printf("All monitors have completed.  Restarting..."));
       
   656 	//Ensure all characters make it to the serial port...
       
   657 	__KTRACE_OPT(KALWAYS,Kern::Printf("                                           "));
       
   658 	if(restartType&ESoftRestart == ESoftRestart)
       
   659 		Kern::Restart(0);
       
   660 	else //EHardRestart
       
   661 		Kern::Restart(0x80000000);
       
   662 	}
       
   663 
       
   664 EXPORT_C void Monitor::RegisterMonitorImpl(Monitor* aImpl)
       
   665 	{
       
   666 	if(TheMonitorPtr == 0)
       
   667 		{
       
   668 		/* TheMonitorPtr should point to the first monitor registered.  Which
       
   669 		 * will be the first one loaded, which is the first one specified in the
       
   670 		 * oby file. */
       
   671 		TheMonitorPtr = aImpl;
       
   672 		__KTRACE_OPT(KDEBUGGER,Kern::Printf("TheMonitorPtr set to: %x", aImpl));
       
   673 		/* Once we have a valid TheMonitorPtr we set the Monitor Entry point to
       
   674 		 * say that there is some sort of crash handling.*/
       
   675 		Epoc::SetMonitorEntryPoint(Monitor::Entry);
       
   676 		}
       
   677 	else
       
   678 		{
       
   679 		TInt i;
       
   680 		for (i = 0; i < MONITOR_MAXCOUNT; ++i)
       
   681 			{
       
   682 			if(TheAltMonitorPtrs[i] == 0)
       
   683 				{
       
   684 				TheAltMonitorPtrs[i] = aImpl;
       
   685 				__KTRACE_OPT(KDEBUGGER,Kern::Printf("TheAltMonitorPtrs[%d] set to: %x", i, TheAltMonitorPtrs[i]));
       
   686 				break;
       
   687 				}
       
   688 			}
       
   689 		if (i == MONITOR_MAXCOUNT)
       
   690 			{
       
   691 			Kern::Fault("Too many crash monitors attempted registration", 0);
       
   692 			}
       
   693 		}
       
   694 	__KTRACE_OPT(KDEBUGGER,Kern::Printf("Registered Monitor: %x", aImpl));
       
   695 	}
       
   696 	
       
   697 #define GETSEGADD(aSeg,aMember)	aSeg, (aSeg==NULL)?0:_LOFF(aSeg,DCodeSeg,aMember)
       
   698 
       
   699 EXPORT_C void Monitor::DisplayCodeSeg(DCodeSeg* aSeg,TBool aFull)
       
   700 	{
       
   701 	TInt i;
       
   702 	
       
   703 	Printf("\r\nCodeSeg at %08x:\r\n",aSeg);
       
   704 	MTRAP(i,Printf("   FileName: %S\r\n",aSeg->iFileName));
       
   705 	if (i!=KErrNone)
       
   706 		ProcessError(i);
       
   707 
       
   708 	Printf("   RunAddress: %08x\r\n",aSeg->iRunAddress);
       
   709 	if (aFull)
       
   710 		{
       
   711 		Printf("\r\n   iLink:     Prev %08x (%08x) Next %08x (%08x)\r\n",GETSEGADD(aSeg->iLink.iPrev,iLink),GETSEGADD(aSeg->iLink.iNext,iLink));
       
   712 		Printf("   iTempLink: Prev %08x (%08x) Next %08x (%08x)\r\n",GETSEGADD(aSeg->iTempLink.iPrev,iTempLink),GETSEGADD(aSeg->iTempLink.iNext,iTempLink));
       
   713 		Printf("   iGbgLink:  Prev %08x (%08x) Next %08x (%08x)\r\n", GETSEGADD(aSeg->iGbgLink.iPrev,iGbgLink),GETSEGADD(aSeg->iGbgLink.iNext,iGbgLink));
       
   714 		Printf("   iAccessCount: %x\r\n",aSeg->iAccessCount);
       
   715 		Printf("   iEntryPtVeneer: %08x\r\n",aSeg->iEntryPtVeneer);
       
   716 		Printf("   iFileEntryPoint: %08x\r\n",aSeg->iFileEntryPoint);
       
   717 		Printf("   iExtOffset: %x\r\n",aSeg->iExtOffset);
       
   718 		Printf("   iUids:");
       
   719 		for (i=0; i<KMaxCheckedUid; i++)
       
   720 			Printf(" %08x",aSeg->iUids.iUid[i]);
       
   721 		Printf("\r\n   iDeps: %08x (",aSeg->iDeps);
       
   722 		if (aSeg->iDepCount<1000) 
       
   723 			for (i=0; i<aSeg->iDepCount; i++)
       
   724 				Printf(" %08x",aSeg->iDeps[i]);
       
   725 			else
       
   726 				Printf("List not shown due to large number");
       
   727 		Printf(" )\r\n   iDepCount: %x\r\n",aSeg->iDepCount);
       
   728 		Printf("   iNextDep: %x\r\n",aSeg->iNextDep);
       
   729 		Printf("   iMark: %x\r\n",aSeg->iMark);
       
   730 		Printf("   iAttr: %x\r\n",aSeg->iAttr);
       
   731 		Printf("   iExeCodeSeg: %08x\r\n",aSeg->iExeCodeSeg);
       
   732 		Printf("   iAttachProcess: %08x\r\n",aSeg->iAttachProcess);
       
   733 		Printf("   iModuleVersion: %x\r\n",aSeg->iModuleVersion);
       
   734 		Printf("   iS:\r\n");
       
   735 		Printf("      SecureId: %08x, VendorId: %08x\r\n",aSeg->iS.iSecureId,aSeg->iS.iVendorId);
       
   736 		Printf("      Caps:");
       
   737 		for (i=0; i<SCapabilitySet::ENCapW; i++)
       
   738 			Printf(" %08x",aSeg->iS.iCaps[i]);
       
   739 		Printf("\r\n   iSize: %x\r\n\r\n",aSeg->iSize);
       
   740 		
       
   741 		Printf("   iXIP: %x\r\n",((DEpocCodeSeg*)aSeg)->iXIP);
       
   742 		Printf("   iInfo: %08x ",((DEpocCodeSeg*)aSeg)->iInfo);
       
   743 		
       
   744 		if (((DEpocCodeSeg*)aSeg)->iXIP==1)
       
   745 			{
       
   746 			Printf("(TRomImageHeader*)\r\n");
       
   747 				MTRAP(i,DisplayTRomImageHeader((TRomImageHeader*) (((DEpocCodeSeg*)aSeg)->iInfo)))			
       
   748 			}
       
   749 		else if (((DEpocCodeSeg*)aSeg)->iXIP==0)
       
   750 			{
       
   751 			Printf("(SRamCodeInfo*)\r\n");
       
   752 			MTRAP(i,DisplaySRamCodeInfo((SRamCodeInfo*) (((DEpocCodeSeg*)aSeg)->iInfo)))			
       
   753 			}
       
   754 		else
       
   755 			{
       
   756 			Printf("(TAny*)\r\n\r\n");
       
   757 			i=KErrNone;
       
   758 			}
       
   759 			
       
   760 		if (i!=KErrNone)
       
   761 			ProcessError(i);
       
   762 
       
   763 		MDisplayCodeSeg(aSeg);
       
   764 		}
       
   765 	}
       
   766 	
       
   767 void Monitor::DisplaySRamCodeInfo(SRamCodeInfo* aS)
       
   768 	{
       
   769 	Printf("      iCodeSize: %08x\r\n", aS->iCodeSize);
       
   770 	Printf("      iTextSize: %08x\r\n",aS->iTextSize);
       
   771 	Printf("      iCodeRunAddr: %08x\r\n",aS->iCodeRunAddr);
       
   772 	Printf("      iCodeLoadAddr: %08x\r\n",aS->iCodeLoadAddr);
       
   773 	Printf("      iDataSize: %08x\r\n",aS->iDataSize);
       
   774 	Printf("      iBssSize: %08x\r\n",aS->iBssSize);
       
   775 	Printf("      iDataRunAddr: %08x\r\n",aS->iDataRunAddr);
       
   776 	Printf("      iDataLoadAddr: %08x\r\n",aS->iDataLoadAddr);
       
   777 	Printf("      iConstOffset: %08x\r\n",aS->iConstOffset);
       
   778 	Printf("      iExportDir: %08x\r\n",aS->iExportDir);
       
   779 	Printf("      iExportDirCount: %08x\r\n",aS->iExportDirCount);
       
   780 	Printf("      iExceptionDescriptor: %08x\r\n\r\n",aS->iExceptionDescriptor);
       
   781 	}
       
   782 
       
   783 void Monitor::DisplayTRomImageHeader(TRomImageHeader* aS)
       
   784 	{
       
   785 	TInt i;
       
   786 	Printf("      iUid1: %08x, iUid2: %08x, iUid3: %08x\r\n", aS->iUid1, aS->iUid2, aS->iUid3);		
       
   787 	Printf("      iUidChecksum: %08x \r\n",aS->iUidChecksum);
       
   788 	Printf("      iEntryPoint:  %08x \r\n",aS->iEntryPoint);	
       
   789 	Printf("      iCodeAddress: %08x, iCodeSize: %08x\r\n",aS->iCodeAddress,aS->iCodeSize);
       
   790 	Printf("      iDataAddress: %08x, iDataSize: %08x\r\n",aS->iDataAddress,aS->iDataSize);
       
   791 	Printf("      iTextSize:    %08x, iBssSize:  %08x\r\n",aS->iTextSize,aS->iBssSize);	 
       
   792 	Printf("      iHeapSizeMin: %08x, iHeapSizeMax: %08x, iStackSize: %08x\r\n",aS->iHeapSizeMin,aS->iHeapSizeMax,aS->iStackSize);
       
   793 	Printf("      iDllRefTable: %08x\r\n",aS->iDllRefTable);
       
   794 	if (aS->iDllRefTable)
       
   795 		{
       
   796 		Printf("          Flags: %04x, NumberOfEntries: %04x\r\n",aS->iDllRefTable->iFlags,aS->iDllRefTable->iNumberOfEntries);
       
   797 		Printf("          Entry:");
       
   798 		for (i=0; i<aS->iDllRefTable->iNumberOfEntries; i++)
       
   799 			Printf(" %08x", aS->iDllRefTable->iEntry[i]);
       
   800 		Printf("\r\n");
       
   801 	}
       
   802 	Printf("      iExportDirCount: %x, iExportDir: %08x\r\n",aS->iExportDirCount, aS->iExportDir);
       
   803 	Printf("      iS:\r\n");
       
   804 	Printf("         SecureId: %08x, VendorId: %08x\r\n",aS->iS.iSecureId,aS->iS.iVendorId);
       
   805 	Printf("         Caps:");
       
   806 	for (i=0; i<SCapabilitySet::ENCapW; i++)
       
   807 		Printf(" %08x",aS->iS.iCaps[i]);
       
   808 	Printf("\r\n      iToolsVersion: Major %02x Minor %02x Build %04x\r\n",aS->iToolsVersion.iMajor, aS->iToolsVersion.iMinor, aS->iToolsVersion.iBuild);
       
   809 	Printf("      iFlags: %08x\r\n",aS->iFlags);
       
   810 	Printf("      iPriority: %x\r\n",aS->iPriority);
       
   811 	Printf("      iDataBssLinearBase: %08x\r\n",aS->iDataBssLinearBase);
       
   812 	Printf("      iNextExtension: %08x\r\n",aS->iNextExtension);
       
   813 	Printf("      iHardwareVariant: %08x\r\n",aS->iHardwareVariant);
       
   814 	Printf("      iTotalDataSize: %08x\r\n",aS->iTotalDataSize);
       
   815 	Printf("      iModuleVersion: %08x\r\n",aS->iModuleVersion);
       
   816 	Printf("      iExceptionDescriptor: %08x\r\n\r\n",aS->iExceptionDescriptor);
       
   817 	}
       
   818 
       
   819 
       
   820 EXPORT_C void Monitor::DisplayCodeSeg(TBool aFull)
       
   821 	{
       
   822 	SDblQue* codeSegList = Kern::CodeSegList();
       
   823 	Printf("Full CodeSeg List:\r\n\r\n");
       
   824 		for (SDblQueLink* codeseg= codeSegList->First(); codeseg!=(SDblQueLink*) codeSegList; codeseg=codeseg->iNext)
       
   825 			{
       
   826 				DisplayCodeSeg(_LOFF(codeseg,DCodeSeg, iLink),aFull);
       
   827 			}	
       
   828 	}
       
   829 GLDEF_C TInt KernelModuleEntry(TInt aReason)
       
   830 	{
       
   831 	return KErrNone;
       
   832 	}
       
   833 
       
   834 
       
   835 /**
       
   836 Time of system crash.
       
   837 
       
   838 @return Time of crash in seconds since 0AD, or zero if crash time un-available.
       
   839 */
       
   840 EXPORT_C TInt64 CrashTime()
       
   841 	{
       
   842 	TInt64 secsSince0AD = 0;
       
   843 	MTRAPD(res, secsSince0AD = (Kern::SystemTime() + 999999) / 1000000);
       
   844 	return secsSince0AD;
       
   845 	}
       
   846 
       
   847