2 #include <e32svr.h> // RDebug
\r
7 void ExceptionHandler(TExcType exc) {}
\r
11 static const wchar_t * const exception_names[] = {
\r
13 L"IntegerDivideByZero",
\r
26 L"FloatDivideByZero",
\r
27 L"FloatInexactResult",
\r
28 L"FloatInvalidOperation",
\r
43 static void getASpace(TUint *code_start, TUint *code_end, TUint *stack_start, TUint *stack_end)
\r
47 TFullName chunkname;
\r
48 TFindChunk findChunk(_L("*"));
\r
50 asm volatile ("str pc, %0" : "=m" (pc) );
\r
51 asm volatile ("str sp, %0" : "=m" (sp) );
\r
53 while( findChunk.Next(chunkname) != KErrNotFound ) {
\r
54 chunk.Open(findChunk);
\r
55 if((TUint)chunk.Base()+chunk.Bottom() < pc && pc < (TUint)chunk.Base()+chunk.Top()) {
\r
56 if(code_start) *code_start = (TUint)chunk.Base()+chunk.Bottom();
\r
57 if(code_end) *code_end = (TUint)chunk.Base()+chunk.Top();
\r
59 if((TUint)chunk.Base()+chunk.Bottom() < sp && sp < (TUint)chunk.Base()+chunk.Top()) {
\r
60 if(stack_start) *stack_start = (TUint)chunk.Base()+chunk.Bottom();
\r
61 if(stack_end) *stack_end = (TUint)chunk.Base()+chunk.Top();
\r
68 #if defined(__DEBUG_PRINT)
\r
69 extern "C" char *debugString();
\r
72 // our very own exception handler
\r
73 void ExceptionHandler(TExcType exc)
\r
76 TUint stack_end = 0; // ending address of our stack chunk
\r
77 TUint code_start = 0, code_end = 0; // starting and ending addresses of our code chunk
\r
78 TUint guessed_address = 0;
\r
80 asm volatile ("str lr, %0" : "=m" (lr) );
\r
81 asm volatile ("str sp, %0" : "=m" (sp) );
\r
83 // first get some info about the chunks we live in
\r
84 getASpace(&code_start, &code_end, 0, &stack_end);
\r
86 // now we begin some black magic tricks
\r
87 // we go up our stack until we pass our caller address
\r
88 for(; sp < stack_end; sp += 4)
\r
89 if(*(TUint *)sp == lr) break;
\r
91 // there might be mirored caller address
\r
92 for(i = sp + 4; i < sp + 0x300 && i < stack_end; i += 4)
\r
93 if(*(TUint *)i == lr) { sp = i; break; }
\r
95 // aah, it is always 0x9c bytes away from the caller address in my firmware,
\r
96 // don't know how to detect it in any other way
\r
98 guessed_address = *(TUint *)sp;
\r
101 TUint exec_show = exc;
\r
102 if(exec_show > 27) exec_show = 27;
\r
103 TPtrC ptrExc((TUint16 *) exception_names[exec_show]);
\r
105 RDebug::Print(_L("!!!Exception %i (%S) @ 0x%08x (guessed; relative=0x%08x)"), exc, &ptrExc, guessed_address, guessed_address - code_start);
\r
106 #ifdef __DEBUG_PRINT_FILE
\r
107 DEBUGPRINT( _L("!!!Exception %i (%S) @ 0x%08x (guessed; relative=0x%08x)"), exc, &ptrExc, guessed_address, guessed_address - code_start);
\r
112 buff1.Copy(_L(" guessed stack: "));
\r
114 for(sp += 4, i = 0; i < 5 && sp < stack_end; sp += 4) {
\r
115 if((*(TUint *)sp >> 28) == 5) {
\r
116 if(i++) buff1.Append(_L(", "));
\r
117 buff2.Format(_L("0x%08x"), *(TUint *)sp);
\r
118 buff1.Append(buff2);
\r
120 else if(code_start < *(TUint *)sp && *(TUint *)sp < code_end) {
\r
121 if(i++) buff1.Append(_L(", "));
\r
122 buff2.Format(_L("0x%08x"), *(TUint *)sp);
\r
123 buff1.Append(buff2);
\r
124 buff1.Append(_L(" ("));
\r
125 buff2.Format(_L("0x%08x"), *(TUint *)sp - code_start);
\r
126 buff1.Append(buff2);
\r
127 buff1.Append(_L(")"));
\r
130 RDebug::Print(_L("%S"), &buff1);
\r
131 #ifdef __DEBUG_PRINT_FILE
\r
132 DEBUGPRINT(_L("%S"), &buff1);
\r
136 #if defined(__DEBUG_PRINT)
\r
137 char *ps, *cstr = debugString();
\r
138 for(ps = cstr; *ps; ps++) {
\r
147 // RDebug::Print(_L("Stack dump:"));
\r
148 // asm volatile ("str sp, %0" : "=m" (sp) );
\r
149 // for(TUint i = sp+0x400; i >= sp-16; i-=4)
\r
150 // RDebug::Print(_L("%08x: %08x"), i, *(int *)i);
\r
152 // more descriptive replacement of "KERN-EXEC 3" panic
\r
153 buff1.Format(_L("K-EX3: %S"), &ptrExc);
\r
154 User::Panic(buff1, exc);
\r
157 #endif // ifdef __WINS__
\r
160 #if defined(__DEBUG_PRINT) || defined(__WINS__)
\r
163 // c string dumper for RDebug::Print()
\r
164 static TBuf<1024> sTextBuffer;
\r
165 TDesC* DO_CONV(const char* s)
\r
167 TPtrC8 text8((TUint8*) (s));
\r
168 sTextBuffer.Copy(text8);
\r
169 return &sTextBuffer;
\r
173 #ifdef __DEBUG_PRINT_C
\r
174 #include <stdarg.h> // va_*
\r
175 #include <stdio.h> // vsprintf
\r
177 // debug print from c code
\r
178 extern "C" void dprintf(char *format, ...)
\r
183 va_start(args,format);
\r
184 vsprintf(buffer,format,args);
\r
187 DEBUGPRINT(_L("%S"), DO_CONV(buffer));
\r
191 #ifdef __DEBUG_PRINT_FILE
\r
192 #include <f32file.h>
\r
194 // note: uses tls, leaks some mem
\r
195 void debugPrintFileInit()
\r
197 RFs *fs = new(ELeave) RFs;
\r
199 RFile *file = new(ELeave) RFile;
\r
201 TInt res = file->Open(*fs, _L("C:\\documents\\Media files\\other\\snes9x.log"), EFileWrite|EFileShareAny);
\r
202 if(res) res = file->Open(*fs, _L("C:\\snes9x.log"), EFileWrite|EFileShareAny);
\r
203 if(!res) { TInt size; file->Size(size); file->Seek(ESeekStart, size); }
\r
205 if(res) res = file->Create(*fs, _L("C:\\documents\\Media files\\other\\snes9x.log"), EFileWrite|EFileShareAny);
\r
206 if(res) res = file->Create(*fs, _L("C:\\snes9x.log"), EFileWrite|EFileShareAny);
\r
207 Dll::SetTls(res ? 0 : file);
\r
210 // debug print to file
\r
211 void debugPrintFile(TRefByValue<const TDesC> aFmt, ...)
\r
214 RFile *file = (RFile *) Dll::Tls();
\r
215 if(!file) return; // shit!
\r
217 TTime now; now.UniversalTime();
\r
219 TBuf8<512> tmpBuff8;
\r
222 file->Size(size); file->Seek(ESeekStart, size); // something else could have written to the file
\r
224 now.FormatL(tmpBuff, _L("%H:%T:%S.%C: "));
\r
225 tmpBuff8.Copy(tmpBuff);
\r
226 file->Write(tmpBuff8);
\r
229 VA_START(args, aFmt);
\r
230 tmpBuff.FormatList(aFmt, args);
\r
232 tmpBuff8.Copy(tmpBuff);
\r
233 file->Write(tmpBuff8);
\r
235 file->Write(TPtrC8((TUint8 const *) "\r\n"));
\r