windowing/windowserver/econs/D_EXC.CPP
changeset 0 5d03bc08d59c
child 33 25f95128741d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/econs/D_EXC.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,362 @@
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+//
+
+#include <e32std.h>
+#include <e32svr.h>
+#include <f32file.h>
+
+_LIT(KBlankLine, "\r");
+
+class TDll
+	{
+public:
+	TDll(const TDesC& aName, TUint8* aBase, TInt aSize)
+		: iName(aName), iBase((TUint)aBase), iSize((TUint)aSize)
+		{}
+
+	TFullName iName;
+	TUint iBase;
+	TUint iSize;
+	};
+
+class TDllList
+	{
+public:
+	static void FindDlls();
+	static void ResetAndDestroy();
+	static void ListDlls(TFileText& aTextFile);
+	static TInt Match(TUint anAddr, const TDll*& aDll);
+
+private:
+	static RPointerArray<TDll> iList;
+	};
+
+RPointerArray<TDll> TDllList::iList(10);
+
+void TDllList::ResetAndDestroy()
+	{
+	iList.ResetAndDestroy();
+	}
+
+void TDllList::ListDlls(TFileText& aTextFile)
+	{
+	TBuf<0x100> line;
+
+	_LIT(KDllFormat, "%08x-%08x %S\r");
+
+	aTextFile.Write(KBlankLine);
+	for (TInt i=0; i<iList.Count(); i++)
+		{
+		const TDll& dll=*(iList[i]);
+		line.Format(KDllFormat, dll.iBase, dll.iBase+dll.iSize-1, &dll.iName);
+		aTextFile.Write(line);
+		}
+	}
+
+TInt TDllList::Match(TUint anAddr, const TDll*& aDll)
+	{
+	for (TInt i=0; i<iList.Count(); i++)
+		{
+		aDll=iList[i];
+		if (aDll->iBase<=anAddr && aDll->iBase+aDll->iSize > anAddr)
+			return KErrNone;
+		}
+	return KErrNotFound;
+	}
+
+
+void TDllList::FindDlls()
+//
+// For each library known to the system, look for a chunk of the same name
+//
+	{
+	TFindLibrary findLib;
+	TFullName libName;
+
+	while (findLib.Next(libName)==KErrNone)
+		{
+		TFindChunk findChunk(libName);
+		TFullName chunkName;
+		if (findChunk.Next(chunkName)!=KErrNone)
+			continue;
+		RChunk chunk;
+		if (chunk.Open(findChunk)!=KErrNone)
+			continue;
+		TUint8* base=chunk.Base();
+		TInt size=chunk.Size();
+		chunk.Close();
+		TDll* dllptr=new TDll(libName,base,size);
+		if (dllptr!=0)
+			iList.Append(dllptr);
+		}
+	}
+
+_LIT(KFormatStackInfo,"Stack %08x-%08x (? %d?), sp=%08x\r");
+//_LIT(KGrabStack,"Capture stack data");
+//_LIT(KNoStack,"Don't risk it");
+
+HBufC8* GrabStack(const TDesC& /*aLine1*/, TThreadId aId, TUint aSp, TInt& aStackBase, TInt& aStackSize)
+	{
+	TInt err=KErrNone;
+#if 0
+	// Defect in E32 162 which means that RThread::GetRamSizes will always reset the machine!
+	RThread thread;
+	if (thread.Open(aId)!=KErrNone)
+		return 0;
+
+	TInt heapsize=0;
+	err=thread.GetRamSizes(heapsize,aStackSize);
+	thread.Close();
+	
+	if (err!=KErrNone)
+		return 0;
+
+	// Sanity check
+	aStackBase = aSp & ~((1024*1024)-1);
+	if (aStackSize<0 || aStackSize>=1024*1024 || aSp>(TUint)(aStackBase+aStackSize))
+		{
+		aStackBase=0;	// indicates a daft stack pointer
+		return 0;
+		}
+#else
+	// Sanity check & guess at stack size
+	aStackBase = aSp & ~((1024*1024)-1);
+	aStackSize = (aSp - aStackBase + 4096) & ~4095;		// round up to a multiple of the page size
+	if (aStackBase+aStackSize-aSp < 200)
+			aStackSize += 4096;		// seems too small - risk another page!
+	if (aStackSize<0 || aStackSize>=1024*1024)
+		{
+		aStackBase=0;	// indicates a daft stack pointer
+		return 0;
+		}
+	aStackSize-=4;	// a clue to the wise that this is a guess...
+#endif
+
+	// Ask the user if we want to risk grabbing the stack...
+
+	TBuf<0x100> line2;
+	line2.Format(KFormatStackInfo, aStackBase, aStackBase+aStackSize-1, aStackSize, aSp);
+    //Don't ask the user just do it for WSERV
+	/*RNotifier ask;
+	if (ask.Connect() != KErrNone)
+		return 0;
+	TRequestStatus status;
+	TInt buttonval=1;
+	ask.Notify(aLine1,line2,KGrabStack,KNoStack,buttonval,status);
+	User::WaitForRequest(status);
+	ask.Close();
+	if (status.Int()!=KErrNone || buttonval != 0)
+		return 0;*/
+
+	// OK - let stack grabbing commence
+	HBufC8* stackbuf = HBufC8::New(aStackSize);
+	if (stackbuf==0)
+		return 0;
+
+	TPtr8 stackdes(stackbuf->Des());
+	err=RDebug::ReadMemory(aId,aStackBase,stackdes,aStackSize);
+	if (err!=KErrNone)
+		{
+		delete stackbuf;
+		stackbuf=0;
+		}
+	return stackbuf;
+	}
+
+GLDEF_C TInt E32Main()
+//
+// Reporting more detail of KERN-EXEC 3 errors
+//
+// Warning: This code uses fragile assumptions which may not be true
+// in future releases of EPOC
+//
+// 1) EXEs are located at 0x20000000
+// 2) the map file for an EXE puts the start of text at 400010
+// 3) the map file for a DLL puts the start of text at 10000010
+// 4) the EPOC ROM lives at address 0x50000000
+// 5) EPOC stacks start at a megabyte boundary
+//
+	{
+	TBuf<0x100> line1;
+	TBuf<0x100> line2;
+	SDebugInfo info;
+	struct SRegisterInfo reginfo;
+	TUint pc;
+	TUint regs[16];
+	const TDll* faultDll;
+
+	_LIT(KInfo1, "D_EXC started");
+	User::InfoPrint(KInfo1);
+
+	TRequestStatus stat(0);
+//	FOREVER
+	for (TInt rep=0; rep<2; rep++)	// die after two exceptions
+		{
+		TInt err;
+		// wait for any thread to panic...
+
+
+		err=RDebug::GetException(info,stat);
+		if (err!=KErrNone)
+			{
+			_LIT(KInfo2, "RDebug failure");
+			User::Panic(KInfo2, err);
+			}
+
+		User::WaitForRequest(stat);
+
+		_LIT(KFormatPanic, "%S panic %S %d\r");
+		_LIT(KFormatException, "%S exception type %d\r");
+		_LIT(KFormatBreakpoint, "%S has breakpoint %d\r");
+
+
+		switch (info.iDebugType)
+			{
+		case EPanic:
+			line1.Format(KFormatPanic,&info.iName,&info.iCategory, info.iPanicType);
+			break;
+		case EException:
+			line1.Format(KFormatException,&info.iName,info.iPanicType);
+			break;
+		case EBreakPoint:
+			line1.Format(KFormatBreakpoint,&info.iName,info.iPanicType);
+			break;
+		default:
+			continue;
+			}
+
+		// assume that it's KERN-EXEC 3 and try to use the 
+		// full RDebug support to locate the faulting instruction
+
+		HBufC8* stack=0;
+		TInt stackbase=0;
+		TInt stacksize=0;
+
+		const TInt KStackPointerReg = 13;
+
+		pc = 0x00000001;	// illegal value
+
+
+		err = RDebug::Open();
+		if (err==KErrNone)
+			{
+			err = RDebug::RegisterInfo(reginfo);
+			if (!err)
+				{
+				RDebug::GetRegister(info.iId,reginfo.iNumberOfPcRegister, pc);
+				for (int i=0; i<16; i++)
+					RDebug::GetRegister(info.iId, i, regs[i]);
+				}
+
+			TDllList::FindDlls();
+
+			stack=GrabStack(line1, info.iId, regs[KStackPointerReg], stackbase, stacksize);
+
+			//RDebug::KillThread(info.iId);
+			RDebug::Close();
+			}
+
+
+		_LIT(KFormatEXE,	"pc=%08x, .map equivalent %08x\r");
+		_LIT(KFormatROM,	"pc=%08x, in ROM\r");
+		_LIT(KFormatDll,	"pc=%08x, in DLL %S, .map equivalent %08x\r");
+		_LIT(KFormatOther,	"pc=%08x, iCodeAddr=%08x\r");
+		_LIT(KFormatError,	"(Unable to determine pc)\r");
+
+		if ((pc&3) == 0)
+			{
+			if (pc >= 0x20000000 && pc < 0x30000000)
+				line2.Format(KFormatEXE, pc, pc-0x20000000+0x400010);
+			else
+			if (pc >= 0x50000000 && pc < 0x60000000)
+				line2.Format(KFormatROM, pc);
+			else
+			if (TDllList::Match(pc, faultDll)==KErrNone)
+				line2.Format(KFormatDll, pc, &faultDll->iName, pc-(faultDll->iBase)+0x10000010);
+
+			else
+				line2.Format(KFormatOther, pc, info.iCodeAddr);
+
+			}
+		else
+			line2.Copy(KFormatError);
+
+		RFs fs;
+		err = fs.Connect();
+		if (err!=KErrNone)
+			break;
+
+		_LIT(KFormatFilename,"d:\\d_exc_%d.txt");
+		_LIT(KFormatStackname,"d:\\d_exc_%d.stk");
+
+		// Report the basic information about registers, DLLs etc
+
+		TFileName name;
+		name.Format(KFormatFilename, *(TUint*)&info.iId);
+
+		RFile file;
+		err=file.Replace(fs, name, EFileWrite+EFileShareAny+EFileStreamText);
+		if (err!=KErrNone)
+			break;
+
+		TFileText textfile;
+		textfile.Set(file);
+
+		textfile.Write(line1);
+		textfile.Write(line2);
+		textfile.Write(KBlankLine);
+
+		_LIT(KFormatRegisters,"r%02d=%08x %08x %08x %08x\r");
+
+		line2.Format(KFormatRegisters, 0, regs[0], regs[1], regs[2], regs[3]);
+		textfile.Write(line2);
+		line2.Format(KFormatRegisters, 4, regs[4], regs[5], regs[6], regs[7]);
+		textfile.Write(line2);
+		line2.Format(KFormatRegisters, 8, regs[8], regs[9], regs[10], regs[11]);
+		textfile.Write(line2);
+		line2.Format(KFormatRegisters, 12,regs[12], regs[13], regs[14], regs[15]);
+		textfile.Write(line2);
+
+		if (stackbase!=0)
+			{
+			line2.Format(KFormatStackInfo, stackbase, stackbase+stacksize-1, stacksize, regs[KStackPointerReg]);
+			textfile.Write(line2);
+			}
+
+		TDllList::ListDlls(textfile);
+		TDllList::ResetAndDestroy();
+
+		file.Close();
+
+		// Dump the stack as binary data
+
+		if (stack)
+			{
+			name.Format(KFormatStackname, *(TUint*)&info.iId);
+			err=file.Replace(fs, name, EFileWrite+EFileShareAny+EFileStreamText);
+			if (err==KErrNone)
+				{
+				file.Write(*stack);
+				file.Close();
+				}
+			}
+		delete stack;
+
+		fs.Close();
+		}
+	return stat.Int();
+	}
+
+