windowing/windowserver/econs/D_EXC.CPP
author Faisal Memon <faisal.memon@nokia.com>
Fri, 25 Jun 2010 17:49:58 +0100
branchEGL_MERGE
changeset 105 158b2308cc08
parent 0 5d03bc08d59c
child 33 25f95128741d
permissions -rw-r--r--
Fix def files so that the implementation agnostic interface definition has no non-standards defined entry points, and change the eglrefimpl specific implementation to place its private entry points high up in the ordinal order space in the implementation region, not the standards based entrypoints region.

// 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();
	}