switch Cyclone to submodule on it's own git repo
[picodrive.git] / platform / uiq2 / debug.cpp
CommitLineData
cc68a136 1\r
2#include <e32svr.h> // RDebug\r
3#include "debug.h"\r
4\r
5#ifdef __WINS__\r
6\r
7void ExceptionHandler(TExcType exc) {}\r
8\r
9#else\r
10\r
11static const wchar_t * const exception_names[] = {\r
12 L"General",\r
13 L"IntegerDivideByZero",\r
14 L"SingleStep",\r
15 L"BreakPoint",\r
16 L"IntegerOverflow",\r
17 L"BoundsCheck",\r
18 L"InvalidOpCode",\r
19 L"DoubleFault",\r
20 L"StackFault",\r
21 L"AccessViolation",\r
22 L"PrivInstruction",\r
23 L"Alignment",\r
24 L"PageFault",\r
25 L"FloatDenormal",\r
26 L"FloatDivideByZero",\r
27 L"FloatInexactResult",\r
28 L"FloatInvalidOperation",\r
29 L"FloatOverflow",\r
30 L"FloatStackCheck",\r
31 L"FloatUnderflow",\r
32 L"Abort",\r
33 L"Kill",\r
34 L"DataAbort",\r
35 L"CodeAbort",\r
36 L"MaxNumber",\r
37 L"InvalidVector",\r
38 L"UserInterrupt",\r
39 L"Unknown"\r
40};\r
41\r
42\r
43static void getASpace(TUint *code_start, TUint *code_end, TUint *stack_start, TUint *stack_end)\r
44{\r
45 TUint pc, sp;\r
46 RChunk chunk;\r
47 TFullName chunkname;\r
48 TFindChunk findChunk(_L("*"));\r
49\r
50 asm volatile ("str pc, %0" : "=m" (pc) );\r
51 asm volatile ("str sp, %0" : "=m" (sp) );\r
52\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
58 } else\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
62 }\r
63 chunk.Close();\r
64 }\r
65}\r
66\r
67// tmp\r
68#if defined(__DEBUG_PRINT)\r
69extern "C" char *debugString();\r
70#endif\r
71\r
72// our very own exception handler\r
73void ExceptionHandler(TExcType exc)\r
74{\r
75 TUint lr, sp, i;\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
79\r
80 asm volatile ("str lr, %0" : "=m" (lr) );\r
81 asm volatile ("str sp, %0" : "=m" (sp) );\r
82\r
83 // first get some info about the chunks we live in\r
84 getASpace(&code_start, &code_end, 0, &stack_end);\r
85\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
90\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
94\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
97 sp += 0x9c;\r
98 guessed_address = *(TUint *)sp;\r
99\r
100 // output the info\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
104\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
108#endif\r
109\r
110 TBuf<148> buff1;\r
111 TBuf<10> buff2;\r
112 buff1.Copy(_L(" guessed stack: "));\r
113\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
119 }\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
128 }\r
129 }\r
130 RDebug::Print(_L("%S"), &buff1);\r
131#ifdef __DEBUG_PRINT_FILE\r
132 DEBUGPRINT(_L("%S"), &buff1);\r
133#endif\r
134\r
135 // tmp\r
136#if defined(__DEBUG_PRINT)\r
137 char *ps, *cstr = debugString();\r
138 for(ps = cstr; *ps; ps++) {\r
139 if(*ps == '\n') {\r
140 *ps = 0;\r
141 dprintf(cstr);\r
142 cstr = ps+1;\r
143 }\r
144 }\r
145#endif\r
146\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
151\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
155}\r
156\r
157#endif // ifdef __WINS__\r
158\r
159\r
160#if defined(__DEBUG_PRINT) || defined(__WINS__)\r
161\r
162#ifndef __DLL__\r
163 // c string dumper for RDebug::Print()\r
164 static TBuf<1024> sTextBuffer;\r
165 TDesC* DO_CONV(const char* s)\r
166 {\r
167 TPtrC8 text8((TUint8*) (s));\r
168 sTextBuffer.Copy(text8);\r
169 return &sTextBuffer;\r
170 }\r
171#endif\r
172\r
173#ifdef __DEBUG_PRINT_C\r
174 #include <stdarg.h> // va_*\r
175 #include <stdio.h> // vsprintf\r
176\r
177 // debug print from c code\r
178 extern "C" void dprintf(char *format, ...)\r
179 {\r
180 va_list args;\r
181 char buffer[512];\r
182\r
183 va_start(args,format);\r
184 vsprintf(buffer,format,args);\r
185 va_end(args);\r
186\r
187 DEBUGPRINT(_L("%S"), DO_CONV(buffer));\r
188 }\r
189#endif\r
190\r
191#ifdef __DEBUG_PRINT_FILE\r
192 #include <f32file.h>\r
193\r
194 // note: uses tls, leaks some mem\r
195 void debugPrintFileInit()\r
196 {\r
197 RFs *fs = new(ELeave) RFs;\r
198 fs->Connect();\r
199 RFile *file = new(ELeave) RFile;\r
200 // try to open\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
204 // try to create\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
208 }\r
209\r
210 // debug print to file\r
211 void debugPrintFile(TRefByValue<const TDesC> aFmt, ...)\r
212 {\r
213 // get RFile\r
214 RFile *file = (RFile *) Dll::Tls();\r
215 if(!file) return; // shit!\r
216\r
217 TTime now; now.UniversalTime();\r
218 TBuf<512> tmpBuff;\r
219 TBuf8<512> tmpBuff8;\r
220 TInt size;\r
221\r
222 file->Size(size); file->Seek(ESeekStart, size); // something else could have written to the file\r
223\r
224 now.FormatL(tmpBuff, _L("%H:%T:%S.%C: "));\r
225 tmpBuff8.Copy(tmpBuff);\r
226 file->Write(tmpBuff8);\r
227\r
228 VA_LIST args;\r
229 VA_START(args, aFmt);\r
230 tmpBuff.FormatList(aFmt, args);\r
231 VA_END(args);\r
232 tmpBuff8.Copy(tmpBuff);\r
233 file->Write(tmpBuff8);\r
234\r
235 file->Write(TPtrC8((TUint8 const *) "\r\n"));\r
236 file->Flush();\r
237 }\r
238#endif\r
239\r
240#endif\r
241\r