initial import
[picodrive.git] / platform / uiq3 / engine / debug.cpp
1 \r
2 #include <e32svr.h> // RDebug\r
3 #include "debug.h"\r
4 \r
5 #ifdef __WINS__\r
6 \r
7 void ExceptionHandler(TExcType exc) {}\r
8 \r
9 #else\r
10 \r
11 static 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
43 static 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
69 extern "C" char *debugString();\r
70 #endif\r
71 \r
72 // our very own exception handler\r
73 void 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         DEBUGPRINT(_L("ExceptionHandler()")); // this seems to never be called\r
81 \r
82         asm volatile ("str lr, %0" : "=m" (lr) );\r
83         asm volatile ("str sp, %0" : "=m" (sp) );\r
84 \r
85         // first get some info about the chunks we live in\r
86         getASpace(&code_start, &code_end, 0, &stack_end);\r
87 \r
88         // now we begin some black magic tricks\r
89         // we go up our stack until we pass our caller address\r
90         for(; sp < stack_end; sp += 4)\r
91                 if(*(TUint *)sp == lr) break;\r
92 \r
93         // there might be mirored caller address\r
94         for(i = sp + 4; i < sp + 0x300 && i < stack_end; i += 4)\r
95                 if(*(TUint *)i == lr) { sp = i; break; }\r
96 \r
97         // aah, it is always 0x9c bytes away from the caller address in my firmware,\r
98         // don't know how to detect it in any other way\r
99         sp += 0x9c;\r
100         guessed_address = *(TUint *)sp;\r
101 \r
102         // output the info\r
103         TUint exec_show = exc;\r
104         if(exec_show > 27) exec_show = 27;\r
105         TPtrC ptrExc((TUint16 *) exception_names[exec_show]);\r
106 \r
107         RDebug::Print(_L("!!!Exception %i (%S) @ 0x%08x (guessed; relative=0x%08x)"), exc, &ptrExc, guessed_address, guessed_address - code_start);\r
108 #ifdef __DEBUG_PRINT_FILE\r
109         DEBUGPRINT(   _L("!!!Exception %i (%S) @ 0x%08x (guessed; relative=0x%08x)"), exc, &ptrExc, guessed_address, guessed_address - code_start);\r
110 #endif\r
111 \r
112         TBuf<148> buff1;\r
113         TBuf<10>  buff2;\r
114         buff1.Copy(_L("  guessed stack: "));\r
115 \r
116         for(sp += 4, i = 0; i < 5 && sp < stack_end; sp += 4) {\r
117                 if((*(TUint *)sp >> 28) == 5) {\r
118                         if(i++) buff1.Append(_L(", "));\r
119                         buff2.Format(_L("0x%08x"), *(TUint *)sp);\r
120                         buff1.Append(buff2);\r
121                 }\r
122                 else if(code_start < *(TUint *)sp && *(TUint *)sp < code_end) {\r
123                         if(i++) buff1.Append(_L(", "));\r
124                         buff2.Format(_L("0x%08x"), *(TUint *)sp);\r
125                         buff1.Append(buff2);\r
126                         buff1.Append(_L(" ("));\r
127                         buff2.Format(_L("0x%08x"), *(TUint *)sp - code_start);\r
128                         buff1.Append(buff2);\r
129                         buff1.Append(_L(")"));\r
130                 }\r
131         }\r
132         RDebug::Print(_L("%S"), &buff1);\r
133 #ifdef __DEBUG_PRINT_FILE\r
134         DEBUGPRINT(_L("%S"), &buff1);\r
135 #endif\r
136 \r
137         // tmp\r
138 #if defined(__DEBUG_PRINT)\r
139         char *ps, *cstr = debugString();\r
140         for(ps = cstr; *ps; ps++) {\r
141           if(*ps == '\n') {\r
142             *ps = 0;\r
143             dprintf(cstr);\r
144                 cstr = ps+1;\r
145           }\r
146         }\r
147 #endif\r
148 \r
149 //      RDebug::Print(_L("Stack dump:"));\r
150 //      asm volatile ("str sp, %0" : "=m" (sp) );\r
151 //      for(TUint i = sp+0x400; i >= sp-16; i-=4)\r
152 //              RDebug::Print(_L("%08x: %08x"), i, *(int *)i);\r
153 \r
154         // more descriptive replacement of "KERN-EXEC 3" panic\r
155         buff1.Format(_L("K-EX3: %S"), &ptrExc);\r
156         User::Panic(buff1, exc);\r
157 }\r
158 \r
159 #endif // ifdef __WINS__\r
160 \r
161 \r
162 #if defined(__DEBUG_PRINT) || defined(__WINS__)\r
163 \r
164 #ifndef __DLL__\r
165         // c string dumper for RDebug::Print()\r
166         static  TBuf<1024> sTextBuffer;\r
167         TDesC* DO_CONV(const char* s)\r
168         {\r
169                 TPtrC8  text8((TUint8*) (s));\r
170                 sTextBuffer.Copy(text8);\r
171                 return &sTextBuffer;\r
172         }\r
173 #endif\r
174 \r
175 #ifdef __DEBUG_PRINT_C\r
176         #include <stdarg.h> // va_*\r
177         #include <stdio.h>  // vsprintf\r
178 \r
179         // debug print from c code\r
180         extern "C" void dprintf(char *format, ...)\r
181         {\r
182                 va_list args;\r
183                 char    buffer[512];\r
184 \r
185                 va_start(args,format);\r
186                 vsprintf(buffer,format,args);\r
187                 va_end(args);\r
188 \r
189                 DEBUGPRINT(_L("%S"), DO_CONV(buffer));\r
190         }\r
191 #endif\r
192 \r
193 #ifdef __DEBUG_PRINT_FILE\r
194         #include <f32file.h>\r
195 \r
196         //static RFile logFile;\r
197 //      static TBool logInited = 0;\r
198         RMutex logMutex;\r
199 \r
200         static void debugPrintFileInit()\r
201         {\r
202                 // try to open\r
203                 logMutex.CreateLocal();\r
204                 RFs fserv;\r
205                 fserv.Connect();\r
206                 RFile logFile;\r
207                 logFile.Replace(fserv, _L("C:\\logs\\pico.log"), EFileWrite|EFileShareAny);\r
208                 logFile.Close();\r
209                 fserv.Close();\r
210         }\r
211 \r
212         // debug print to file\r
213         void debugPrintFile(TRefByValue<const TDesC> aFmt, ...)\r
214         {\r
215                 if (logMutex.Handle() <= 0) debugPrintFileInit();\r
216 \r
217                 logMutex.Wait();\r
218                 RFs fserv;\r
219                 fserv.Connect();\r
220 \r
221                 TTime now; now.UniversalTime();\r
222                 TBuf<512>  tmpBuff;\r
223                 TBuf8<512> tmpBuff8;\r
224                 TInt size, res;\r
225 \r
226                 RThread thisThread;\r
227                 RFile logFile;\r
228                 res = logFile.Open(fserv, _L("C:\\logs\\pico.log"), EFileWrite|EFileShareAny);\r
229                 if(res) goto fail1;\r
230 \r
231                 logFile.Size(size); logFile.Seek(ESeekStart, size);\r
232 \r
233                 now.FormatL(tmpBuff, _L("%H:%T:%S.%C: "));\r
234                 tmpBuff8.Copy(tmpBuff);\r
235                 logFile.Write(tmpBuff8);\r
236 \r
237                 tmpBuff8.Format(TPtr8((TUint8 *)"%03i: ", 6, 6), (TInt32) thisThread.Id());\r
238                 logFile.Write(tmpBuff8);\r
239 \r
240                 VA_LIST args;\r
241                 VA_START(args, aFmt);\r
242                 tmpBuff.FormatList(aFmt, args);\r
243                 VA_END(args);\r
244                 tmpBuff8.Copy(tmpBuff);\r
245                 logFile.Write(tmpBuff8);\r
246 \r
247                 logFile.Write(TPtrC8((TUint8 const *) "\n"));\r
248                 logFile.Flush();\r
249                 logFile.Close();\r
250                 fail1:\r
251                 thisThread.Close();\r
252                 fserv.Close();\r
253 \r
254                 logMutex.Signal();\r
255         }\r
256 #endif\r
257 \r
258 #endif\r
259 \r