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