1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - OS
3 File: os_callTrace.c
4
5 Copyright 2003-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17 #include <nitro/os.h>
18
19 #if defined(OS_PROFILE_AVAILABLE) && defined(OS_PROFILE_CALL_TRACE)
20
21 #ifdef OS_NO_CALLTRACE
22 //---- dummy function
__PROFILE_ENTRY(void)23 SDK_WEAK_SYMBOL asm void __PROFILE_ENTRY( void ){ bx lr }
__PROFILE_EXIT(void)24 SDK_WEAK_SYMBOL asm void __PROFILE_EXIT( void ){ bx lr }
OS_DumpThreadCallTrace(const OSThread *)25 void OS_DumpThreadCallTrace(const OSThread *)
26 {
27 }
28 #else // ifdef OS_NO_CALLTRACE
29
30 //---- function prototype declaration
31 OSCallTraceInfo *OSi_GetCallTraceInfo(void);
32 void OSi_DumpCurrentLr(u32 lr, int strIndex);
33 void OSi_DumpOneInfo(OSCallTrace *p);
34 void OSi_DumpFullInfo(OSCallTraceInfo *info);
35 void OSi_DumpCallTrace_core(u32 returnAddress);
36 void OSi_DumpThreadCallTrace_core(const OSThread *thread, u32 returnAddress);
37 void OSi_Abort_CallTraceFull(u32 name, u32 returnAddress, u32 r0, u32 sp);
38 void OSi_Abort_CallTraceLess(u32 returnAddress);
39
40 //---- pointer to callTraceInfo at not using threadSystem
41 static OSCallTraceInfo *OSi_DefaultCallTraceInfo;
42
43 #define OSi_STR_DUMPCALLTRACE 0
44 #define OSi_STR_DUMPTHREADCALLTRACE 1
45
46 extern BOOL OSi_IsThreadInitialized;
47
48 //================================================================================
49 // ENABLE/DISABLE
50 //================================================================================
51 /*---------------------------------------------------------------------------*
52 Name: OS_EnableCallTrace
53
54 Description: enable callTrace
55
56 Arguments: None
57
58 Returns: previous status. TRUE if enable
59 *---------------------------------------------------------------------------*/
60 #include <nitro/code32.h>
OS_EnableCallTrace(void)61 asm BOOL OS_EnableCallTrace( void )
62 {
63 //---- check if callTrace not available
64 stmfd sp!, {lr}
65 bl OSi_GetCallTraceInfo
66 ldmfd sp!, {lr}
67 cmp r0, #0
68 bxeq lr
69
70 mov r2, r0
71 ldrh r0, [ r2, #OSCallTraceInfo.enable ]
72 mov r1, #1
73 strh r1, [ r2, #OSCallTraceInfo.enable ]
74
75 bx lr
76 }
77 #include <nitro/codereset.h>
78
79 /*---------------------------------------------------------------------------*
80 Name: OS_DisableCallTrace
81
82 Description: disble callTrace
83
84 Arguments: None
85
86 Returns: previous status. TRUE if enable
87 *---------------------------------------------------------------------------*/
88 #include <nitro/code32.h>
OS_DisableCallTrace(void)89 asm BOOL OS_DisableCallTrace( void )
90 {
91 //---- check if callTrace not available
92 stmfd sp!, {lr}
93 bl OSi_GetCallTraceInfo
94 ldmfd sp!, {lr}
95 cmp r0, #0
96 bxeq lr
97
98 mov r2, r0
99 ldrh r0, [ r2, #OSCallTraceInfo.enable ]
100 mov r1, #0
101 strh r1, [ r2, #OSCallTraceInfo.enable ]
102
103 bx lr
104 }
105 #include <nitro/codereset.h>
106
107 /*---------------------------------------------------------------------------*
108 Name: OS_RestoreCallTrace
109
110 Description: set status of callTrace
111
112 Arguments: enable : TRUE if set to be enable, FALSE if not
113
114 Returns: previous status. TRUE if enable
115 *---------------------------------------------------------------------------*/
116 #include <nitro/code32.h>
OS_RestoreCallTrace(BOOL)117 asm BOOL OS_RestoreCallTrace( BOOL )
118 {
119 //---- check if callTrace not available
120 stmfd sp!, {r0, lr}
121 bl OSi_GetCallTraceInfo
122 mov r1, r0
123 ldmfd sp!, {r0, lr}
124 cmp r1, #0
125 bxeq lr
126
127 ldrh r2, [ r1, #OSCallTraceInfo.enable ]
128 strh r0, [ r1, #OSCallTraceInfo.enable ]
129 mov r0, r2
130
131 bx lr
132 }
133 #include <nitro/codereset.h>
134
135
136 //================================================================================
137 // SETTING
138 //================================================================================
139 /*---------------------------------------------------------------------------*
140 Name: OS_InitCallTrace
141
142 Description: Initialize callTrace stack,
143 and start recording trace.
144
145 Arguments: buf address to record trace infomation
146 size size of buffer (by byte)
147
148 Returns: None
149 *---------------------------------------------------------------------------*/
150 #pragma profile off
OS_InitCallTrace(void * buf,u32 size,OSCallTraceMode mode)151 void OS_InitCallTrace(void *buf, u32 size, OSCallTraceMode mode)
152 {
153 OSCallTraceInfo **infoPtr;
154
155 SDK_ASSERTMSG(((u32)buf & 3) == 0, "CallTrace buffer must be aligned by 4");
156 SDK_ASSERTMSG((size >= OSi_TRACEINFO_SIZEOF_HEADERPART + sizeof(OSCallTrace)),
157 "to small CallTrace buffer");
158
159 #ifdef SDK_NO_THREAD
160 //---- pointer to callTraceInfo is in static valiable
161 infoPtr = &OSi_DefaultCallTraceInfo;
162 #else
163 SDK_ASSERTMSG(OS_IsThreadAvailable(), "CallTrace need thread system.");
164 //---- pointer to callTraceInfo is in OSThread structure
165 infoPtr = (OSCallTraceInfo **)&(OS_GetCurrentThread()->profiler);
166 #endif
167
168 *infoPtr = (OSCallTraceInfo *)buf;
169 (*infoPtr)->current = (*infoPtr)->array;
170 (*infoPtr)->limit = (OSCallTrace *)((u32)buf
171 + OSi_TRACEINFO_SIZEOF_HEADERPART
172 + OS_CalcCallTraceLines(size) * sizeof(OSCallTrace));
173 (*infoPtr)->enable = (u16)TRUE;
174 (*infoPtr)->circular = (u16)mode;
175 #ifdef OS_CALLTRACE_LEVEL_AVAILABLE
176 (*infoPtr)->level = 0;
177 #endif
178
179 //---- clear buffer if used for logging
180 if (mode == OS_CALLTRACE_LOG)
181 {
182 OS_ClearCallTraceBuffer();
183 }
184 }
185
186 #pragma profile reset
187
188 //================================================================================
189 // UTILITY
190 //================================================================================
191 /*---------------------------------------------------------------------------*
192 Name: OS_CalcCallTraceLines
193
194 Description: calculate number of lines to be able to be allocated
195
196 Arguments: size : CallTrace buffer size
197 same as argument of OS_InitCallTrace()'s size
198
199 Returns: number of lines to be able to allocate in 'size' byte
200 *---------------------------------------------------------------------------*/
OS_CalcCallTraceLines(u32 size)201 int OS_CalcCallTraceLines(u32 size)
202 {
203 int n = (int)((size - OSi_TRACEINFO_SIZEOF_HEADERPART) / sizeof(OSCallTrace));
204
205 return (n < 0) ? 0 : n;
206 }
207
208 /*---------------------------------------------------------------------------*
209 Name: OS_CalcCallTraceBufferSize
210
211 Description: calculate buffer size to allocate specified lines
212
213 Arguments: lines : lines to want to allocate
214
215 Returns: buffer size to need
216 *---------------------------------------------------------------------------*/
OS_CalcCallTraceBufferSize(int lines)217 u32 OS_CalcCallTraceBufferSize(int lines)
218 {
219 SDK_ASSERT(lines >= 0);
220 return OSi_TRACEINFO_SIZEOF_HEADERPART + lines * sizeof(OSCallTrace);
221 }
222
223 /*---------------------------------------------------------------------------*
224 Name: OS_ClearCallTraceBuffer
225
226 Description: clear buffer if used for logging
227
228 Arguments: None
229
230 Returns: None
231 *---------------------------------------------------------------------------*/
232 #pragma profile off
OS_ClearCallTraceBuffer(void)233 void OS_ClearCallTraceBuffer(void)
234 {
235
236 OSCallTraceInfo *info = OSi_GetCallTraceInfo();
237
238 if (info && info->circular)
239 {
240 OSCallTrace *p;
241
242 info->current = info->array;
243 for (p = info->current; p < info->limit; p++)
244 {
245 p->name = (u32)NULL;
246 }
247 }
248 }
249
250 #pragma profile reset
251
252 /*---------------------------------------------------------------------------*
253 Name: OSi_SetCallTraceEntry
254
255 Description: store dummy string pointer
256
257 Arguments: name : pointer to string to be stored as function name
258 lr : value to be stored as lr
259
260 Returns: None
261 *---------------------------------------------------------------------------*/
262 #pragma profile off
OSi_SetCallTraceEntry(const char * name,u32 lr)263 void OSi_SetCallTraceEntry(const char *name, u32 lr)
264 {
265
266 OSCallTraceInfo *info = OSi_GetCallTraceInfo();
267
268 if (info && info->circular)
269 {
270 OSCallTrace *p = info->current;
271
272 p->name = (u32)name;
273 p->returnAddress = lr;
274
275 #ifdef OS_CALLTRACE_RECORD_R0
276 p->r0 = 0;
277 #endif
278 #ifdef OS_CALLTRACE_RECORD_R1
279 p->r1 = 0;
280 #endif
281 #ifdef OS_CALLTRACE_RECORD_R2
282 p->r2 = 0;
283 #endif
284 #ifdef OS_CALLTRACE_RECORD_R3
285 p->r3 = 0;
286 #endif
287 p++;
288
289 if ((u32)p >= (u32)info->limit)
290 {
291 p = info->array;
292 }
293
294 info->current = p;
295 }
296 }
297
298 #pragma profile reset
299
300 /*---------------------------------------------------------------------------*
301 Name: OSi_GetCallTraceInfo
302
303 Description: get pointer to callTraceInfo structure
304
305 Arguments: None
306
307 Returns: pointer.
308 NULL if not callTrace initialized
309 *---------------------------------------------------------------------------*/
310 #include <nitro/code32.h>
OSi_GetCallTraceInfo(void)311 asm OSCallTraceInfo* OSi_GetCallTraceInfo( void )
312 {
313 #ifdef SDK_NO_THREAD
314 ldr r0, =OSi_DefaultCallTraceInfo
315 ldr r0, [ r0, #0 ]
316 bx lr
317 #else
318 ldr r0, =OSi_ThreadInfo
319 ldr r0, [ r0, #OSThreadInfo.current ] // r0 = currentThread. 0 if no currentThread
320 cmp r0, #0
321 ldrne r0, [ r0, #OSThread.profiler ] // r0 = callTraceInfo
322 bx lr
323 #endif
324 }
325 #include <nitro/codereset.h>
326
327 //================================================================================
328 // PROFILE
329 //================================================================================
330 /*---------------------------------------------------------------------------*
331 Name: __PROFILE_ENTRY
332
333 Description: entry of function in profiler
334
335 Arguments: None
336
337 Returns: None
338 *---------------------------------------------------------------------------*/
339 #include <nitro/code32.h>
__PROFILE_ENTRY(void)340 asm void __PROFILE_ENTRY( void )
341 {
342 #ifndef SDK_NO_THREAD
343 stmfd sp!, {r0}
344 ldr r0, =OSi_IsThreadInitialized
345 ldr r0, [ r0, #0 ]
346 cmp r0, #0
347 ldmfd sp!, {r0}
348 bxeq lr
349 #endif
350
351 stmfd sp!, {r1-r3}
352
353 //---- check if callTrace not available
354 stmfd sp!, {r0, lr}
355 bl OSi_GetCallTraceInfo
356 mov r1, r0 // r1 = callTraceInfo
357 ldmfd sp!, {r0, lr}
358 cmp r1, #0
359 beq _exit
360
361 //---- check if callTrace master enable
362 ldrh r2, [ r1, #OSCallTraceInfo.enable ]
363 cmp r2, #0
364 beq _exit
365
366 //---- get currentPtr of CallTrace
367 ldr r2, [ r1, #OSCallTraceInfo.current ] // r2 = currentPtr of trace
368 cmp r2, #0
369 beq _exit
370
371 //---- if circular
372 ldrh r3, [ r1, #OSCallTraceInfo.circular ]
373 cmp r3, #0
374 bne _circular_skip_overcheck
375
376 //---- check if trace buffer is over limit
377 #ifdef OS_CALLTRACE_CHECK_OVERSTACK
378 ldr r3, [ r1, #OSCallTraceInfo.limit ]
379 cmp r2, r3
380 ldrpl r1, [ sp, #16 ] // lr
381 ldrpl r2, [ sp, #12 ] // r0
382 movpl r3, sp // sp ( r1,r2,r3 stored )
383 bpl OSi_Abort_CallTraceFull
384 #endif
385
386 _circular_skip_overcheck:
387 //---- store pointer to function name string
388 str r0, [ r2, #OSCallTrace.name ]
389
390 //---- store lr register
391 ldr r0, [ sp, #16 ]
392 str r0, [ r2, #OSCallTrace.returnAddress ]
393
394 #ifdef OS_CALLTRACE_RECORD_R0
395 //---- store r0 register
396 ldr r0, [ sp, #12 ]
397 str r0, [ r2, #OSCallTrace.r0 ]
398 #endif
399
400 #ifdef OS_CALLTRACE_RECORD_R1
401 //---- store r1 register
402 ldr r0, [ sp, #0 ]
403 str r0, [ r2, #OSCallTrace.r1 ]
404 #endif
405
406 #ifdef OS_CALLTRACE_RECORD_R2
407 //---- store r2 register
408 ldr r0, [ sp, #4 ]
409 str r0, [ r2, #OSCallTrace.r2 ]
410 #endif
411
412 #ifdef OS_CALLTRACE_RECORD_R3
413 //---- store r3 register
414 ldr r0, [ sp, #8 ]
415 str r0, [ r2, #OSCallTrace.r3 ]
416 #endif
417
418 #ifdef OS_CALLTRACE_LEVEL_AVAILABLE
419 //---- store call level
420 ldr r0, [ r1, #OSCallTraceInfo.level ]
421 str r0, [ r2, #OSCallTrace.level ]
422 add r0, r0, #1
423 str r0, [ r1, #OSCallTraceInfo.level ]
424 #endif
425
426 //---- increment pointer
427 add r2, r2, #OSi_SIZEOF_CALLTRACE
428
429 //---- if circular then buffer is ring-buf
430 ldrh r3, [ r1, #OSCallTraceInfo.circular ]
431 cmp r3, #0
432 beq _notcircular_skip_ring
433 ldr r3, [ r1, #OSCallTraceInfo.limit ]
434 cmp r2, r3
435 bmi _store_current
436 add r2, r1, #OSCallTraceInfo.array
437
438 _notcircular_skip_ring:
439 _store_current:
440 str r2, [ r1, #OSCallTraceInfo.current ]
441
442 _exit:
443 ldmfd sp!, {r1-r3}
444 bx lr
445 }
446 #include <nitro/codereset.h>
447
448 /*---------------------------------------------------------------------------*
449 Name: __PROFILE_EXIT
450
451 Description: exit of function in profiler
452
453 Arguments: None
454
455 Returns: None
456 *---------------------------------------------------------------------------*/
457 #include <nitro/code32.h>
__PROFILE_EXIT(void)458 asm void __PROFILE_EXIT( void )
459 {
460 #ifdef OS_CALLTRACE_CHECK_OVERSTACK
461 stmfd sp!, {r0-r2, lr}
462 #else
463 stmfd sp!, {r0-r1, lr}
464 #endif
465
466 #ifndef SDK_NO_THREAD
467 ldr r0, =OSi_IsThreadInitialized
468 ldr r0, [ r0, #0 ]
469 cmp r0, #0
470 beq _exit
471 #endif
472
473 //---- check if callTrace not available
474 bl OSi_GetCallTraceInfo
475 cmp r0, #0
476 beq _exit
477
478 //---- check if callTrace master enable
479 ldrh r1, [ r0, #OSCallTraceInfo.enable ]
480 cmp r1, #0
481 beq _exit
482
483 #ifdef OS_CALLTRACE_LEVEL_AVAILABLE
484 //---- decrement level
485 ldr r1, [ r0, #OSCallTraceInfo.level ]
486 sub r1, r1, #1
487 movmi r1, #0
488 str r1, [ r0, #OSCallTraceInfo.level ]
489 #endif
490
491 //---- if circular then do nothing
492 ldrh r1, [ r0, #OSCallTraceInfo.circular ]
493 cmp r1, #0
494 bne _exit
495
496 //---- decrement current pointer
497 ldr r1, [ r0, #OSCallTraceInfo.current ] // r1 = current
498 sub r1, r1, #OSi_SIZEOF_CALLTRACE
499
500 //---- check if trace buffer is over limit
501 #ifdef OS_CALLTRACE_CHECK_OVERSTACK
502 add r2, r0, #OSCallTraceInfo.array
503
504 cmp r1, r2
505 ldrmi r0, [ sp, #12 ] // lr
506 bmi OSi_Abort_CallTraceLess
507 #endif
508
509 //---- store current pointer
510 str r1, [ r0, #OSCallTraceInfo.current ]
511
512 _exit:
513 #ifdef OS_CALLTRACE_CHECK_OVERSTACK
514 ldmfd sp!, {r0-r2, lr}
515 #else
516 ldmfd sp!, {r0-r1, lr}
517 #endif
518 bx lr
519 }
520 #include <nitro/codereset.h>
521
522 //================================================================================
523 // DUMP
524 //================================================================================
525 /*---------------------------------------------------------------------------*
526 Name: OSi_DumpCurrentLr
527
528 Description: dump current lr register
529
530 Arguments: lr value of lr register
531
532 Returns: None
533 *---------------------------------------------------------------------------*/
534 const char *OSi_DumpCurrentLr_str[] = {
535 "OS_DumpCallTrace", "OS_DumpThreadCallTrace",
536 };
537 #pragma profile off
OSi_DumpCurrentLr(u32 lr,int strIndex)538 void OSi_DumpCurrentLr(u32 lr, int strIndex)
539 {
540 BOOL e = OS_DisableCallTrace();
541 OS_Printf("%s: lr=%08x\n", OSi_DumpCurrentLr_str[strIndex], lr);
542 (void)OS_RestoreCallTrace(e);
543 }
544
545 #pragma profile reset
546
547 /*---------------------------------------------------------------------------*
548 Name: OSi_DumpOneInfo
549
550 Description: dump one OSCallTrace line
551 normaly, only call from OSi_DumpFullInfo
552
553 Arguments: p OSCallTrace pointer
554
555 Returns: None
556 *---------------------------------------------------------------------------*/
557 #pragma profile off
558 #define OSi_CALLTRACE_MAX_INDENT 10
OSi_DumpOneInfo(OSCallTrace * p)559 void OSi_DumpOneInfo(OSCallTrace *p)
560 {
561
562 #ifdef OS_CALLTRACE_LEVEL_AVAILABLE
563 {
564 int n = (int)p->level;
565 if (n > OSi_CALLTRACE_MAX_INDENT)
566 {
567 n = OSi_CALLTRACE_MAX_INDENT;
568 }
569
570 while (n)
571 {
572 int space = n;
573 if (space >= 10)
574 {
575 space = 10;
576 }
577 OS_Printf("%s", &(" \0"[10 - space]));
578 n -= space;
579 }
580 }
581 #endif
582
583 OS_Printf("%s: lr=%08x"
584 #ifdef OS_CALLTRACE_RECORD_R0
585 ", r0=%08x"
586 #endif
587 #ifdef OS_CALLTRACE_RECORD_R1
588 ", r1=%08x"
589 #endif
590 #ifdef OS_CALLTRACE_RECORD_R2
591 ", r2=%08x"
592 #endif
593 #ifdef OS_CALLTRACE_RECORD_R3
594 ", r3=%08x"
595 #endif
596 "\n", (char *)(p->name), p->returnAddress
597 #ifdef OS_CALLTRACE_RECORD_R0
598 , p->r0
599 #endif
600 #ifdef OS_CALLTRACE_RECORD_R1
601 , p->r1
602 #endif
603 #ifdef OS_CALLTRACE_RECORD_R2
604 , p->r2
605 #endif
606 #ifdef OS_CALLTRACE_RECORD_R3
607 , p->r3
608 #endif
609 );
610 }
611
612 #pragma profile reset
613
614 /*---------------------------------------------------------------------------*
615 Name: OSi_DumpFullInfo
616
617 Description: dump one OSCallTrace line
618 normaly, only call from OSi_DumpCallTrace_core and OSi_DumpThreadCallTrace_core
619
620 Arguments: info OSCallTraceInfo pointer
621
622 Returns: None
623 *---------------------------------------------------------------------------*/
624 #pragma profile off
OSi_DumpFullInfo(OSCallTraceInfo * info)625 void OSi_DumpFullInfo(OSCallTraceInfo *info)
626 {
627 if (info && info->current)
628 {
629 OSCallTrace *p = info->current - 1;
630
631 while (1)
632 {
633 if (info->circular && (u32)p < (u32)info->array)
634 {
635 p = info->limit - 1;
636 }
637
638 if ((u32)p < (u32)info->array
639 || 0x2000000 > (u32)(p->name) || 0x2400000 < (u32)(p->name))
640 {
641 break;
642 }
643
644 OSi_DumpOneInfo(p);
645
646 if ((u32)p == (u32)(info->current))
647 {
648 break;
649 }
650
651 p--;
652 }
653 }
654 }
655
656 #pragma profile reset
657
658
659 /*---------------------------------------------------------------------------*
660 Name: OS_DumpCallTrace
661
662 Description: dump callStack
663
664 Arguments: None
665
666 Returns: None
667 *---------------------------------------------------------------------------*/
668 #include <nitro/code32.h>
OS_DumpCallTrace(void)669 asm void OS_DumpCallTrace( void )
670 {
671 mov r0, lr
672 b OSi_DumpCallTrace_core
673
674 // no 'bx lr'
675 }
676 #include <nitro/codereset.h>
677
678 /*---------------------------------------------------------------------------*
679 Name: OSi_DumpCallTrace_core
680
681 Description: dump callTrace (core function)
682
683 Arguments: returnAddress : lr (for display)
684
685 Returns: None
686 *---------------------------------------------------------------------------*/
687 #pragma profile off
OSi_DumpCallTrace_core(u32 returnAddress)688 void OSi_DumpCallTrace_core(u32 returnAddress)
689 {
690 BOOL e = OS_DisableCallTrace();
691
692 OSCallTraceInfo *info = OSi_GetCallTraceInfo();
693 SDK_ASSERTMSG(info && info->current, "Not Initialize functionTrace");
694
695 if (returnAddress)
696 {
697 OSi_DumpCurrentLr(returnAddress, OSi_STR_DUMPCALLTRACE);
698 }
699 OSi_DumpFullInfo(info);
700
701 (void)OS_RestoreCallTrace(e);
702 }
703
704 #pragma profile reset
705
706 /*---------------------------------------------------------------------------*
707 Name: OS_DumpThreadCallTrace
708
709 Description: dump callTrace of thread
710
711 Arguments: thread : thread
712
713 Returns: None
714 *---------------------------------------------------------------------------*/
715 #include <nitro/code32.h>
OS_DumpThreadCallTrace(const OSThread * thread)716 asm void OS_DumpThreadCallTrace( const OSThread* thread )
717 {
718 mov r1, lr
719 b OSi_DumpThreadCallTrace_core
720
721 // no 'bx lr'
722 }
723 #include <nitro/codereset.h>
724
725 /*---------------------------------------------------------------------------*
726 Name: OSi_DumpThreadCallTrace_core
727
728 Description: dump callTrace of thread
729
730 Arguments: thread : thread
731 returnAddress : lr (for display)
732
733 Returns: None
734 *---------------------------------------------------------------------------*/
OSi_DumpThreadCallTrace_core(const OSThread * thread,u32 returnAddress)735 void OSi_DumpThreadCallTrace_core(const OSThread *thread, u32 returnAddress)
736 {
737 OSCallTraceInfo *info;
738 BOOL e;
739
740 #ifdef SDK_NO_THREAD
741 return;
742 #endif
743
744 //---- null means current thread
745 if (!thread)
746 {
747 thread = OS_GetCurrentThread();
748 }
749
750 //---- get callTraceInfo
751 if (thread)
752 {
753 info = (OSCallTraceInfo *)thread->profiler;
754 }
755
756 //---- check callTraceInfo available
757 if (!thread || !info || !info->current)
758 {
759 return;
760 }
761
762 //---- arrange returnAddress
763 if (thread != OS_GetCurrentThread())
764 {
765 returnAddress = thread->context.r[14];
766 }
767
768 e = OS_DisableCallTrace();
769
770 if (returnAddress)
771 {
772 OSi_DumpCurrentLr(returnAddress, OSi_STR_DUMPTHREADCALLTRACE);
773 }
774 OSi_DumpFullInfo(info);
775
776 (void)OS_RestoreCallTrace(e);
777 }
778
779 //================================================================================
780 // ERROR ABORT
781 //================================================================================
782 /*---------------------------------------------------------------------------*
783 Name: OSi_Abort_CallTraceFull
784
785 Description: display error in stack overflow
786
787 Arguments: name function name pointer
788 returnAddress lr
789 r0 r0 (if use)
790
791 Returns: None
792 *---------------------------------------------------------------------------*/
793 #pragma profile off
OSi_Abort_CallTraceFull(u32 name,u32 returnAddress,u32 r0,u32 sp)794 void OSi_Abort_CallTraceFull(u32 name, u32 returnAddress, u32 r0, u32 sp)
795 {
796 #pragma unused( r0 )
797
798 BOOL e = OS_DisableCallTrace(); // not restore status in this function.
799
800 OS_Printf("***Error: CallTrace stack overflow");
801 OS_Printf(" in %s: lr=%08x"
802 #ifdef OS_CALLTRACE_RECORD_R0
803 ", r0=%08x"
804 #endif
805 #ifdef OS_CALLTRACE_RECORD_R1
806 ", r1=%08x"
807 #endif
808 #ifdef OS_CALLTRACE_RECORD_R2
809 ", r2=%08x"
810 #endif
811 #ifdef OS_CALLTRACE_RECORD_R3
812 ", r3=%08x"
813 #endif
814 "\n", (char *)(name), returnAddress
815 #ifdef OS_CALLTRACE_RECORD_R0
816 , r0
817 #endif
818 #ifdef OS_CALLTRACE_RECORD_R1
819 , *((u32 *)sp)
820 #endif
821 #ifdef OS_CALLTRACE_RECORD_R2
822 , *((u32 *)sp + 1)
823 #endif
824 #ifdef OS_CALLTRACE_RECORD_R3
825 , *((u32 *)sp + 2)
826 #endif
827 );
828
829 #ifdef SDK_NO_THREAD
830 OSi_DumpCallTrace_core(0);
831 #else
832 OSi_DumpThreadCallTrace_core(NULL, 0);
833 #endif
834
835 OS_Terminate();
836 }
837
838 #pragma profile reset
839
840 /*---------------------------------------------------------------------------*
841 Name: OSi_Abort_CallTraceLess
842
843 Description: display error in stack underflow
844
845 Arguments: returnAddress lr
846
847 Returns: None
848 *---------------------------------------------------------------------------*/
849 #pragma profile off
OSi_Abort_CallTraceLess(u32 returnAddress)850 void OSi_Abort_CallTraceLess(u32 returnAddress)
851 {
852 BOOL e = OS_DisableCallTrace(); // not restore status in this function.
853
854 OS_Printf("***Error: CallTrace stack underflow.");
855 OS_Printf(" (lr=%08x)\n", returnAddress);
856
857 OS_Terminate();
858 }
859
860 #pragma profile reset
861
862 #endif // ifdef OS_NO_CALLTRACE
863 #endif // defined(OS_PROFILE_AVAILABLE) && defined(OS_PROFILE_CALL_TRACE)
864