--- /dev/null
+\r
+#include <e32svr.h> // RDebug\r
+#include "debug.h"\r
+\r
+#ifdef __WINS__\r
+\r
+void ExceptionHandler(TExcType exc) {}\r
+\r
+#else\r
+\r
+static const wchar_t * const exception_names[] = {\r
+ L"General",\r
+ L"IntegerDivideByZero",\r
+ L"SingleStep",\r
+ L"BreakPoint",\r
+ L"IntegerOverflow",\r
+ L"BoundsCheck",\r
+ L"InvalidOpCode",\r
+ L"DoubleFault",\r
+ L"StackFault",\r
+ L"AccessViolation",\r
+ L"PrivInstruction",\r
+ L"Alignment",\r
+ L"PageFault",\r
+ L"FloatDenormal",\r
+ L"FloatDivideByZero",\r
+ L"FloatInexactResult",\r
+ L"FloatInvalidOperation",\r
+ L"FloatOverflow",\r
+ L"FloatStackCheck",\r
+ L"FloatUnderflow",\r
+ L"Abort",\r
+ L"Kill",\r
+ L"DataAbort",\r
+ L"CodeAbort",\r
+ L"MaxNumber",\r
+ L"InvalidVector",\r
+ L"UserInterrupt",\r
+ L"Unknown"\r
+};\r
+\r
+\r
+static void getASpace(TUint *code_start, TUint *code_end, TUint *stack_start, TUint *stack_end)\r
+{\r
+ TUint pc, sp;\r
+ RChunk chunk;\r
+ TFullName chunkname;\r
+ TFindChunk findChunk(_L("*"));\r
+\r
+ asm volatile ("str pc, %0" : "=m" (pc) );\r
+ asm volatile ("str sp, %0" : "=m" (sp) );\r
+\r
+ while( findChunk.Next(chunkname) != KErrNotFound ) {\r
+ chunk.Open(findChunk);\r
+ if((TUint)chunk.Base()+chunk.Bottom() < pc && pc < (TUint)chunk.Base()+chunk.Top()) {\r
+ if(code_start) *code_start = (TUint)chunk.Base()+chunk.Bottom();\r
+ if(code_end) *code_end = (TUint)chunk.Base()+chunk.Top();\r
+ } else\r
+ if((TUint)chunk.Base()+chunk.Bottom() < sp && sp < (TUint)chunk.Base()+chunk.Top()) {\r
+ if(stack_start) *stack_start = (TUint)chunk.Base()+chunk.Bottom();\r
+ if(stack_end) *stack_end = (TUint)chunk.Base()+chunk.Top();\r
+ }\r
+ chunk.Close();\r
+ }\r
+}\r
+\r
+// tmp\r
+#if defined(__DEBUG_PRINT)\r
+extern "C" char *debugString();\r
+#endif\r
+\r
+// our very own exception handler\r
+void ExceptionHandler(TExcType exc)\r
+{\r
+ TUint lr, sp, i;\r
+ TUint stack_end = 0; // ending address of our stack chunk\r
+ TUint code_start = 0, code_end = 0; // starting and ending addresses of our code chunk\r
+ TUint guessed_address = 0;\r
+\r
+ DEBUGPRINT(_L("ExceptionHandler()")); // this seems to never be called\r
+\r
+ asm volatile ("str lr, %0" : "=m" (lr) );\r
+ asm volatile ("str sp, %0" : "=m" (sp) );\r
+\r
+ // first get some info about the chunks we live in\r
+ getASpace(&code_start, &code_end, 0, &stack_end);\r
+\r
+ // now we begin some black magic tricks\r
+ // we go up our stack until we pass our caller address\r
+ for(; sp < stack_end; sp += 4)\r
+ if(*(TUint *)sp == lr) break;\r
+\r
+ // there might be mirored caller address\r
+ for(i = sp + 4; i < sp + 0x300 && i < stack_end; i += 4)\r
+ if(*(TUint *)i == lr) { sp = i; break; }\r
+\r
+ // aah, it is always 0x9c bytes away from the caller address in my firmware,\r
+ // don't know how to detect it in any other way\r
+ sp += 0x9c;\r
+ guessed_address = *(TUint *)sp;\r
+\r
+ // output the info\r
+ TUint exec_show = exc;\r
+ if(exec_show > 27) exec_show = 27;\r
+ TPtrC ptrExc((TUint16 *) exception_names[exec_show]);\r
+\r
+ RDebug::Print(_L("!!!Exception %i (%S) @ 0x%08x (guessed; relative=0x%08x)"), exc, &ptrExc, guessed_address, guessed_address - code_start);\r
+#ifdef __DEBUG_PRINT_FILE\r
+ DEBUGPRINT( _L("!!!Exception %i (%S) @ 0x%08x (guessed; relative=0x%08x)"), exc, &ptrExc, guessed_address, guessed_address - code_start);\r
+#endif\r
+\r
+ TBuf<148> buff1;\r
+ TBuf<10> buff2;\r
+ buff1.Copy(_L(" guessed stack: "));\r
+\r
+ for(sp += 4, i = 0; i < 5 && sp < stack_end; sp += 4) {\r
+ if((*(TUint *)sp >> 28) == 5) {\r
+ if(i++) buff1.Append(_L(", "));\r
+ buff2.Format(_L("0x%08x"), *(TUint *)sp);\r
+ buff1.Append(buff2);\r
+ }\r
+ else if(code_start < *(TUint *)sp && *(TUint *)sp < code_end) {\r
+ if(i++) buff1.Append(_L(", "));\r
+ buff2.Format(_L("0x%08x"), *(TUint *)sp);\r
+ buff1.Append(buff2);\r
+ buff1.Append(_L(" ("));\r
+ buff2.Format(_L("0x%08x"), *(TUint *)sp - code_start);\r
+ buff1.Append(buff2);\r
+ buff1.Append(_L(")"));\r
+ }\r
+ }\r
+ RDebug::Print(_L("%S"), &buff1);\r
+#ifdef __DEBUG_PRINT_FILE\r
+ DEBUGPRINT(_L("%S"), &buff1);\r
+#endif\r
+\r
+ // tmp\r
+#if defined(__DEBUG_PRINT)\r
+ char *ps, *cstr = debugString();\r
+ for(ps = cstr; *ps; ps++) {\r
+ if(*ps == '\n') {\r
+ *ps = 0;\r
+ dprintf(cstr);\r
+ cstr = ps+1;\r
+ }\r
+ }\r
+#endif\r
+\r
+// RDebug::Print(_L("Stack dump:"));\r
+// asm volatile ("str sp, %0" : "=m" (sp) );\r
+// for(TUint i = sp+0x400; i >= sp-16; i-=4)\r
+// RDebug::Print(_L("%08x: %08x"), i, *(int *)i);\r
+\r
+ // more descriptive replacement of "KERN-EXEC 3" panic\r
+ buff1.Format(_L("K-EX3: %S"), &ptrExc);\r
+ User::Panic(buff1, exc);\r
+}\r
+\r
+#endif // ifdef __WINS__\r
+\r
+\r
+#if defined(__DEBUG_PRINT) || defined(__WINS__)\r
+\r
+#ifndef __DLL__\r
+ // c string dumper for RDebug::Print()\r
+ static TBuf<1024> sTextBuffer;\r
+ TDesC* DO_CONV(const char* s)\r
+ {\r
+ TPtrC8 text8((TUint8*) (s));\r
+ sTextBuffer.Copy(text8);\r
+ return &sTextBuffer;\r
+ }\r
+#endif\r
+\r
+#ifdef __DEBUG_PRINT_C\r
+ #include <stdarg.h> // va_*\r
+ #include <stdio.h> // vsprintf\r
+\r
+ // debug print from c code\r
+ extern "C" void dprintf(char *format, ...)\r
+ {\r
+ va_list args;\r
+ char buffer[512];\r
+\r
+ va_start(args,format);\r
+ vsprintf(buffer,format,args);\r
+ va_end(args);\r
+\r
+ DEBUGPRINT(_L("%S"), DO_CONV(buffer));\r
+ }\r
+#endif\r
+\r
+#ifdef __DEBUG_PRINT_FILE\r
+ #include <f32file.h>\r
+\r
+ //static RFile logFile;\r
+// static TBool logInited = 0;\r
+ RMutex logMutex;\r
+\r
+ static void debugPrintFileInit()\r
+ {\r
+ // try to open\r
+ logMutex.CreateLocal();\r
+ RFs fserv;\r
+ fserv.Connect();\r
+ RFile logFile;\r
+ logFile.Replace(fserv, _L("C:\\logs\\pico.log"), EFileWrite|EFileShareAny);\r
+ logFile.Close();\r
+ fserv.Close();\r
+ }\r
+\r
+ // debug print to file\r
+ void debugPrintFile(TRefByValue<const TDesC> aFmt, ...)\r
+ {\r
+ if (logMutex.Handle() <= 0) debugPrintFileInit();\r
+\r
+ logMutex.Wait();\r
+ RFs fserv;\r
+ fserv.Connect();\r
+\r
+ TTime now; now.UniversalTime();\r
+ TBuf<512> tmpBuff;\r
+ TBuf8<512> tmpBuff8;\r
+ TInt size, res;\r
+\r
+ RThread thisThread;\r
+ RFile logFile;\r
+ res = logFile.Open(fserv, _L("C:\\logs\\pico.log"), EFileWrite|EFileShareAny);\r
+ if(res) goto fail1;\r
+\r
+ logFile.Size(size); logFile.Seek(ESeekStart, size);\r
+\r
+ now.FormatL(tmpBuff, _L("%H:%T:%S.%C: "));\r
+ tmpBuff8.Copy(tmpBuff);\r
+ logFile.Write(tmpBuff8);\r
+\r
+ tmpBuff8.Format(TPtr8((TUint8 *)"%03i: ", 6, 6), (TInt32) thisThread.Id());\r
+ logFile.Write(tmpBuff8);\r
+\r
+ VA_LIST args;\r
+ VA_START(args, aFmt);\r
+ tmpBuff.FormatList(aFmt, args);\r
+ VA_END(args);\r
+ tmpBuff8.Copy(tmpBuff);\r
+ logFile.Write(tmpBuff8);\r
+\r
+ logFile.Write(TPtrC8((TUint8 const *) "\n"));\r
+ logFile.Flush();\r
+ logFile.Close();\r
+ fail1:\r
+ thisThread.Close();\r
+ fserv.Close();\r
+\r
+ logMutex.Signal();\r
+ }\r
+#endif\r
+\r
+#endif\r
+\r