To the best of my knowledge it can't be done.
What I've done is use simple function tracing logic so when a panic happens I have a stack trace at the point of the panic in my the panic handling code (which I log out). This works well except for the fact that you have to remember to add your macro's at the beginning of every function.
e.g.
#ifndef NDEBUG
class __FTrace
{
__FTrace(const char* function)
{
TraceManager::GetInstance().EnterFunction(function);
}
~__FTrace()
{
TraceManager::GetInstance().LeaveFunction(function);
}
};
#define FTRACE() __FTrace(__PRETTY_FUNCTION__)
#else
#define FTRACE()
#endif
void Func()
{
FTRACE();
...
}
For ALLOC's, I've had a lot of success with the Hook Logger under the emulator. It's a real pain to setup and use but it will make it real easy to track down ALLOC memory leaks.
UPDATE: As requested, here is what my panic handling code looks like. Note that my application has to run in the background all the time, so it's setup to restart the app when something bad happens. Also this code works for 3rd Edition SDK's, I haven't tried it on later versions of the SDK's.
The point is to run the main application in another thread and then wait for it to exit. Then check to see why the thread exits, it the thread as exited for unknown reasons, log stuff like my own stack trace and restart the application.
TInt StartMainThread(TAny*)
{
FTRACE();
__LOGSTR_TOFILE("Main Thread Start");
TInt result(KErrNone);
TRAPD(err, result = EikStart::RunApplication(NewApplication));
if(KErrNone != err || KErrNone != result )
{
__LOGSTR_TOFILE("EikStart::RunApplication error: trap(%d), %d", err, result);
}
__LOGSTR_TOFILE("Main Thread End");
return result;
}
const TInt KMainThreadToLiveInSeconds = 10;
} // namespace *unnamed*
LOCAL_C CApaApplication* NewApplication()
{
FTRACE();
return new CMainApplication;
}
GLDEF_C TInt E32Main()
{
#ifdef NDEBUG
__LOGSTR_TOFILE("Application Start (release)");
#else
__LOGSTR_TOFILE("Application Start (debug)");
#endif
#ifndef NO_TRACING
__TraceManager::NewL();
#endif // !NO_TRACING
RHeap& heap(User::Heap());
TInt heapsize=heap.MaxLength();
TInt exitReason(KErrNone);
TTime timeToLive;
timeToLive.UniversalTime();
timeToLive += TTimeIntervalSeconds(KMainThreadToLiveInSeconds);
LManagedHandle<RThread> mainThread;
TInt err = mainThread->Create(_L("Main Thread"), StartMainThread, KDefaultStackSize, KMinHeapSize, heapsize, NULL);
if (KErrNone != err)
{
__LOGSTR_TOFILE("MainThread failed : %d", err);
return err;
}
mainThread->SetPriority(EPriorityNormal);
TRequestStatus status;
mainThread->Logon(status);
mainThread->Resume();
User::WaitForRequest(status);
exitReason = mainThread->ExitReason();
TExitCategoryName category(mainThread->ExitCategory());
switch(mainThread->ExitType())
{
case EExitKill:
__LOGSTR_TOFILE("ExitKill : (%S) : %d", &category, exitReason);
break;
case EExitTerminate:
__LOGSTR_TOFILE("ExitTerminate : (%S) : %d", &category, exitReason);
break;
case EExitPanic:
__LOGSTR_TOFILE("ExitPanic : (%S) : %d", &category, exitReason);
break;
default:
__LOGSTR_TOFILE("ExitUnknown : (%S) : %d", &category, exitReason);
break;
}
#ifndef NO_TRACING
__TraceManager::GetInstance().LogStackTrace();
#endif // NO_TRACING
if( KErrNone != status.Int() )
{
TTime now;
now.UniversalTime();
if (timeToLive > now)
{
TTimeIntervalMicroSeconds diff = timeToLive.MicroSecondsFrom(now);
__LOGSTR_TOFILE("Exiting due to TTL : (%Lu)", diff.Int64());
}
else
{
RProcess current;
RProcess restart;
err = restart.Create(current.FileName(), _L(""));
if( KErrNone == err )
{
__LOGSTR_TOFILE("Restarting...");
restart.Resume();
return KErrNone;
}
else
{
__LOGSTR_TOFILE("Failed to start app: %d", err);
}
}
}
__LOGSTR_TOFILE("Application End");
return exitReason;
}