diff -r 000000000000 -r 5d03bc08d59c windowing/windowserver/econs/D_EXC.CPP --- /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 +#include +#include + +_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 iList; + }; + +RPointerArray 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; iiBase<=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(); + } + +