initial import
[picodrive.git] / platform / uiq3 / engine / debug.cpp
diff --git a/platform/uiq3/engine/debug.cpp b/platform/uiq3/engine/debug.cpp
new file mode 100644 (file)
index 0000000..c532187
--- /dev/null
@@ -0,0 +1,259 @@
+\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