debug.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. #include <e32svr.h> // RDebug
  2. #include "debug.h"
  3. //#define LOG_FILE "C:\\logs\\pico.log"
  4. #define LOG_FILE _L("D:\\pico.log")
  5. #ifdef __WINS__
  6. void ExceptionHandler(TExcType exc) {}
  7. #else
  8. static const wchar_t * const exception_names[] = {
  9. L"General",
  10. L"IntegerDivideByZero",
  11. L"SingleStep",
  12. L"BreakPoint",
  13. L"IntegerOverflow",
  14. L"BoundsCheck",
  15. L"InvalidOpCode",
  16. L"DoubleFault",
  17. L"StackFault",
  18. L"AccessViolation",
  19. L"PrivInstruction",
  20. L"Alignment",
  21. L"PageFault",
  22. L"FloatDenormal",
  23. L"FloatDivideByZero",
  24. L"FloatInexactResult",
  25. L"FloatInvalidOperation",
  26. L"FloatOverflow",
  27. L"FloatStackCheck",
  28. L"FloatUnderflow",
  29. L"Abort",
  30. L"Kill",
  31. L"DataAbort",
  32. L"CodeAbort",
  33. L"MaxNumber",
  34. L"InvalidVector",
  35. L"UserInterrupt",
  36. L"Unknown"
  37. };
  38. #if 0
  39. static void getASpace(TUint *code_start, TUint *code_end, TUint *stack_start, TUint *stack_end)
  40. {
  41. TUint pc, sp;
  42. RChunk chunk;
  43. TFullName chunkname;
  44. TFindChunk findChunk(_L("*"));
  45. asm volatile ("str pc, %0" : "=m" (pc) );
  46. asm volatile ("str sp, %0" : "=m" (sp) );
  47. while( findChunk.Next(chunkname) != KErrNotFound ) {
  48. chunk.Open(findChunk);
  49. if((TUint)chunk.Base()+chunk.Bottom() < pc && pc < (TUint)chunk.Base()+chunk.Top()) {
  50. if(code_start) *code_start = (TUint)chunk.Base()+chunk.Bottom();
  51. if(code_end) *code_end = (TUint)chunk.Base()+chunk.Top();
  52. } else
  53. if((TUint)chunk.Base()+chunk.Bottom() < sp && sp < (TUint)chunk.Base()+chunk.Top()) {
  54. if(stack_start) *stack_start = (TUint)chunk.Base()+chunk.Bottom();
  55. if(stack_end) *stack_end = (TUint)chunk.Base()+chunk.Top();
  56. }
  57. chunk.Close();
  58. }
  59. }
  60. #endif
  61. // tmp
  62. #if defined(__DEBUG_PRINT)
  63. extern "C" char *PDebugMain();
  64. #endif
  65. // our very own exception handler
  66. void ExceptionHandler(TExcType exc)
  67. {
  68. DEBUGPRINT(_L("ExceptionHandler() called!!!")); // this seems to never be called
  69. #if 0
  70. TUint lr, sp, i;
  71. TUint stack_end = 0; // ending address of our stack chunk
  72. TUint code_start = 0, code_end = 0; // starting and ending addresses of our code chunk
  73. TUint guessed_address = 0;
  74. asm volatile ("str lr, %0" : "=m" (lr) );
  75. asm volatile ("str sp, %0" : "=m" (sp) );
  76. // first get some info about the chunks we live in
  77. getASpace(&code_start, &code_end, 0, &stack_end);
  78. // now we begin some black magic tricks
  79. // we go up our stack until we pass our caller address
  80. for(; sp < stack_end; sp += 4)
  81. if(*(TUint *)sp == lr) break;
  82. // there might be mirored caller address
  83. for(i = sp + 4; i < sp + 0x300 && i < stack_end; i += 4)
  84. if(*(TUint *)i == lr) { sp = i; break; }
  85. // aah, it is always 0x9c bytes away from the caller address in my firmware,
  86. // don't know how to detect it in any other way
  87. sp += 0x9c;
  88. guessed_address = *(TUint *)sp;
  89. // output the info
  90. TUint exec_show = exc;
  91. if(exec_show > 27) exec_show = 27;
  92. TPtrC ptrExc((TUint16 *) exception_names[exec_show]);
  93. RDebug::Print(_L("!!!Exception %i (%S) @ 0x%08x (guessed; relative=0x%08x)"), exc, &ptrExc, guessed_address, guessed_address - code_start);
  94. #ifdef __DEBUG_PRINT_FILE
  95. DEBUGPRINT( _L("!!!Exception %i (%S) @ 0x%08x (guessed; relative=0x%08x)"), exc, &ptrExc, guessed_address, guessed_address - code_start);
  96. #endif
  97. TBuf<148> buff1;
  98. TBuf<10> buff2;
  99. buff1.Copy(_L(" guessed stack: "));
  100. for(sp += 4, i = 0; i < 5 && sp < stack_end; sp += 4) {
  101. if((*(TUint *)sp >> 28) == 5) {
  102. if(i++) buff1.Append(_L(", "));
  103. buff2.Format(_L("0x%08x"), *(TUint *)sp);
  104. buff1.Append(buff2);
  105. }
  106. else if(code_start < *(TUint *)sp && *(TUint *)sp < code_end) {
  107. if(i++) buff1.Append(_L(", "));
  108. buff2.Format(_L("0x%08x"), *(TUint *)sp);
  109. buff1.Append(buff2);
  110. buff1.Append(_L(" ("));
  111. buff2.Format(_L("0x%08x"), *(TUint *)sp - code_start);
  112. buff1.Append(buff2);
  113. buff1.Append(_L(")"));
  114. }
  115. }
  116. RDebug::Print(_L("%S"), &buff1);
  117. #ifdef __DEBUG_PRINT_FILE
  118. DEBUGPRINT(_L("%S"), &buff1);
  119. #endif
  120. // tmp
  121. #if defined(__DEBUG_PRINT)
  122. char *ps, *cstr = PDebugMain();
  123. for(ps = cstr; *ps; ps++) {
  124. if(*ps == '\n') {
  125. *ps = 0;
  126. lprintf(cstr);
  127. cstr = ps+1;
  128. }
  129. }
  130. #endif
  131. // RDebug::Print(_L("Stack dump:"));
  132. // asm volatile ("str sp, %0" : "=m" (sp) );
  133. // for(TUint i = sp+0x400; i >= sp-16; i-=4)
  134. // RDebug::Print(_L("%08x: %08x"), i, *(int *)i);
  135. // more descriptive replacement of "KERN-EXEC 3" panic
  136. buff1.Format(_L("K-EX3: %S"), &ptrExc);
  137. User::Panic(buff1, exc);
  138. #endif
  139. }
  140. #endif // ifdef __WINS__
  141. #if 1 // def __DEBUG_PRINT_C
  142. #include <stdarg.h> // va_*
  143. #include <stdio.h> // vsprintf
  144. // debug print from c code
  145. extern "C" void lprintf(char *format, ...)
  146. {
  147. va_list args;
  148. char buffer[512];
  149. int len;
  150. va_start(args,format);
  151. len = vsprintf(buffer,format,args);
  152. va_end(args);
  153. if (buffer[len-1] == '\n')
  154. buffer[len-1] = 0;
  155. DEBUGPRINT(_L("%S"), DO_CONV(buffer));
  156. }
  157. #endif
  158. #if defined(__DEBUG_PRINT) || defined(__WINS__)
  159. #ifndef __DLL__
  160. // c string dumper for RDebug::Print()
  161. static TBuf<1024> sTextBuffer;
  162. TDesC* DO_CONV(const char* s)
  163. {
  164. TPtrC8 text8((TUint8*) (s));
  165. sTextBuffer.Copy(text8);
  166. return &sTextBuffer;
  167. }
  168. #endif
  169. #ifdef __DEBUG_PRINT_FILE
  170. #include <f32file.h>
  171. //static RFile logFile;
  172. // static TBool logInited = 0;
  173. RMutex logMutex;
  174. static void debugPrintFileInit()
  175. {
  176. // try to open
  177. logMutex.CreateLocal();
  178. /*RFs fserv;
  179. fserv.Connect();
  180. RFile logFile;
  181. logFile.Replace(fserv, LOG_FILE, EFileWrite|EFileShareAny);
  182. logFile.Close();
  183. fserv.Close();*/
  184. }
  185. // debug print to file
  186. void debugPrintFile(TRefByValue<const TDesC> aFmt, ...)
  187. {
  188. if (logMutex.Handle() <= 0) debugPrintFileInit();
  189. logMutex.Wait();
  190. RFs fserv;
  191. fserv.Connect();
  192. TTime now; now.UniversalTime();
  193. TBuf<512> tmpBuff;
  194. TBuf8<512> tmpBuff8;
  195. TInt size, res;
  196. RThread thisThread;
  197. RFile logFile;
  198. res = logFile.Open(fserv, LOG_FILE, EFileWrite|EFileShareAny);
  199. if(res) goto fail1;
  200. logFile.Size(size); logFile.Seek(ESeekStart, size);
  201. now.FormatL(tmpBuff, _L("%H:%T:%S.%C: "));
  202. tmpBuff8.Copy(tmpBuff);
  203. logFile.Write(tmpBuff8);
  204. tmpBuff8.Format(TPtr8((TUint8 *)"%03i: ", 6, 6), (TInt32) thisThread.Id());
  205. logFile.Write(tmpBuff8);
  206. VA_LIST args;
  207. VA_START(args, aFmt);
  208. tmpBuff.FormatList(aFmt, args);
  209. VA_END(args);
  210. tmpBuff8.Copy(tmpBuff);
  211. logFile.Write(tmpBuff8);
  212. logFile.Write(TPtrC8((TUint8 const *) "\n"));
  213. logFile.Flush();
  214. logFile.Close();
  215. fail1:
  216. thisThread.Close();
  217. fserv.Close();
  218. logMutex.Signal();
  219. }
  220. #endif
  221. #endif