25
25
* 2022-08-30 Yunjie make rt_vsnprintf adapt to ti c28x (16bit int)
26
26
* 2023-02-02 Bernard add Smart ID for logo version show
27
27
* 2023-10-16 Shell Add hook point for rt_malloc services
28
+ * 2023-10-21 Shell support the common backtrace API which is arch-independent
28
29
* 2023-12-10 xqyjlj perf rt_hw_interrupt_disable/enable, fix memheap lock
29
30
* 2024-03-10 Meco Man move std libc related functions to rtklibc
30
31
*/
31
32
32
33
#include <rtthread.h>
34
+
35
+ /* include rt_hw_backtrace macro defined in cpuport.h */
36
+ #define RT_HW_INCLUDE_CPUPORT
33
37
#include <rthw.h>
34
38
35
39
#define DBG_TAG "kernel.service"
@@ -86,6 +90,34 @@ rt_weak void rt_hw_cpu_shutdown(void)
86
90
return ;
87
91
}
88
92
93
+ /**
94
+ * @note can be overridden by cpuport.h which is defined by a specific arch
95
+ */
96
+ #ifndef RT_HW_BACKTRACE_FRAME_GET_SELF
97
+
98
+ #ifdef __GNUC__
99
+ #define RT_HW_BACKTRACE_FRAME_GET_SELF (frame ) do { \
100
+ (frame)->fp = (rt_base_t)__builtin_frame_address(0U); \
101
+ (frame)->pc = ({__label__ pc; pc: (rt_base_t)&&pc;}); \
102
+ } while (0)
103
+
104
+ #else
105
+ #define RT_HW_BACKTRACE_FRAME_GET_SELF (frame ) do { \
106
+ (frame)->fp = 0; \
107
+ (frame)->pc = 0; \
108
+ } while (0)
109
+
110
+ #endif /* __GNUC__ */
111
+
112
+ #endif /* RT_HW_BACKTRACE_FRAME_GET_SELF */
113
+
114
+ /**
115
+ * @brief Get the inner most frame of target thread
116
+ *
117
+ * @param thread the thread which frame belongs to
118
+ * @param frame the specified frame to be unwound
119
+ * @return rt_err_t 0 is succeed, otherwise a failure
120
+ */
89
121
rt_weak rt_err_t rt_hw_backtrace_frame_get (rt_thread_t thread , struct rt_hw_backtrace_frame * frame )
90
122
{
91
123
RT_UNUSED (thread );
@@ -95,6 +127,13 @@ rt_weak rt_err_t rt_hw_backtrace_frame_get(rt_thread_t thread, struct rt_hw_back
95
127
return - RT_ENOSYS ;
96
128
}
97
129
130
+ /**
131
+ * @brief Unwind the target frame
132
+ *
133
+ * @param thread the thread which frame belongs to
134
+ * @param frame the specified frame to be unwound
135
+ * @return rt_err_t 0 is succeed, otherwise a failure
136
+ */
98
137
rt_weak rt_err_t rt_hw_backtrace_frame_unwind (rt_thread_t thread , struct rt_hw_backtrace_frame * frame )
99
138
{
100
139
RT_UNUSED (thread );
@@ -356,27 +395,34 @@ rt_weak int rt_kprintf(const char *fmt, ...)
356
395
RTM_EXPORT (rt_kprintf );
357
396
#endif /* RT_USING_CONSOLE */
358
397
359
- #ifdef __GNUC__
398
+ /**
399
+ * @brief Print backtrace of current thread to system console device
400
+ *
401
+ * @return rt_err_t 0 is success, otherwise a failure
402
+ */
360
403
rt_weak rt_err_t rt_backtrace (void )
361
404
{
362
- struct rt_hw_backtrace_frame frame = {
363
- .fp = (rt_base_t )__builtin_frame_address (0U ),
364
- .pc = ({__label__ pc ; pc : (rt_base_t )&& pc ;})
365
- };
366
- rt_hw_backtrace_frame_unwind (rt_thread_self (), & frame );
367
- return rt_backtrace_frame (& frame );
368
- }
405
+ struct rt_hw_backtrace_frame frame ;
406
+ rt_thread_t thread = rt_thread_self ();
369
407
370
- #else /* otherwise not implemented */
371
- rt_weak rt_err_t rt_backtrace (void )
372
- {
373
- /* LOG_W cannot work under this environment */
374
- rt_kprintf ("%s is not implemented\n" , __func__ );
375
- return - RT_ENOSYS ;
408
+ RT_HW_BACKTRACE_FRAME_GET_SELF (& frame );
409
+ if (!frame .fp )
410
+ return - RT_EINVAL ;
411
+
412
+ /* we don't want this frame to be printed which is nearly garbage info */
413
+ rt_hw_backtrace_frame_unwind (thread , & frame );
414
+
415
+ return rt_backtrace_frame (thread , & frame );
376
416
}
377
- #endif
378
417
379
- rt_err_t rt_backtrace_frame (struct rt_hw_backtrace_frame * frame )
418
+ /**
419
+ * @brief Print backtrace from frame to system console device
420
+ *
421
+ * @param thread the thread which frame belongs to
422
+ * @param frame where backtrace starts from
423
+ * @return rt_err_t 0 is success, otherwise a failure
424
+ */
425
+ rt_weak rt_err_t rt_backtrace_frame (rt_thread_t thread , struct rt_hw_backtrace_frame * frame )
380
426
{
381
427
long nesting = 0 ;
382
428
@@ -385,7 +431,7 @@ rt_err_t rt_backtrace_frame(struct rt_hw_backtrace_frame *frame)
385
431
while (nesting < RT_BACKTRACE_LEVEL_MAX_NR )
386
432
{
387
433
rt_kprintf (" 0x%lx" , (rt_ubase_t )frame -> pc );
388
- if (rt_hw_backtrace_frame_unwind (rt_thread_self () , frame ))
434
+ if (rt_hw_backtrace_frame_unwind (thread , frame ))
389
435
{
390
436
break ;
391
437
}
@@ -395,6 +441,89 @@ rt_err_t rt_backtrace_frame(struct rt_hw_backtrace_frame *frame)
395
441
return RT_EOK ;
396
442
}
397
443
444
+ /**
445
+ * @brief Print backtrace from buffer to system console
446
+ *
447
+ * @param buffer where traced frames saved
448
+ * @param buflen number of items in buffer
449
+ * @return rt_err_t 0 is success, otherwise a failure
450
+ */
451
+ rt_weak rt_err_t rt_backtrace_formatted_print (rt_ubase_t * buffer , long buflen )
452
+ {
453
+ rt_kprintf ("please use: addr2line -e rtthread.elf -a -f" );
454
+
455
+ for (size_t i = 0 ; i < buflen && buffer [i ] != 0 ; i ++ )
456
+ {
457
+ rt_kprintf (" 0x%lx" , (rt_ubase_t )buffer [i ]);
458
+ }
459
+
460
+ rt_kprintf ("\n" );
461
+ return RT_EOK ;
462
+ }
463
+
464
+
465
+ /**
466
+ * @brief Print backtrace from frame to the given buffer
467
+ *
468
+ * @param frame where backtrace starts from. NULL if it's the current one
469
+ * @param skip the number of frames to discarded counted from calling function.
470
+ * Noted that the inner most frame is always discarded and not counted,
471
+ * which is obviously reasonable since that's this function itself.
472
+ * @param buffer where traced frames saved
473
+ * @param buflen max number of items can be saved in buffer. If there are no more
474
+ * than buflen items to be saved, there will be a NULL after the
475
+ * last saved item in the buffer.
476
+ * @return rt_err_t 0 is success, otherwise a failure
477
+ */
478
+ rt_weak rt_err_t rt_backtrace_to_buffer (rt_thread_t thread ,
479
+ struct rt_hw_backtrace_frame * frame ,
480
+ long skip ,
481
+ rt_ubase_t * buffer ,
482
+ long buflen )
483
+ {
484
+ long nesting = 0 ;
485
+ struct rt_hw_backtrace_frame cur_frame ;
486
+
487
+ if (!thread )
488
+ return - RT_EINVAL ;
489
+
490
+ RT_ASSERT (rt_object_get_type (& thread -> parent ) == RT_Object_Class_Thread );
491
+
492
+ if (!frame )
493
+ {
494
+ frame = & cur_frame ;
495
+ RT_HW_BACKTRACE_FRAME_GET_SELF (frame );
496
+ if (!frame -> fp )
497
+ return - RT_EINVAL ;
498
+ }
499
+
500
+ /* discard frames as required. The inner most is always threw. */
501
+ do {
502
+ rt_hw_backtrace_frame_unwind (thread , frame );
503
+ } while (skip -- > 0 );
504
+
505
+ while (nesting < buflen )
506
+ {
507
+ * buffer ++ = (rt_ubase_t )frame -> pc ;
508
+ if (rt_hw_backtrace_frame_unwind (thread , frame ))
509
+ {
510
+ break ;
511
+ }
512
+ nesting ++ ;
513
+ }
514
+
515
+ if (nesting < buflen )
516
+ * buffer = RT_NULL ;
517
+
518
+ return RT_EOK ;
519
+ }
520
+
521
+ /**
522
+ * @brief Print backtrace of a thread to system console device
523
+ *
524
+ * @param thread which call stack is traced
525
+ * @return rt_err_t 0 is success, otherwise a failure
526
+ */
398
527
rt_err_t rt_backtrace_thread (rt_thread_t thread )
399
528
{
400
529
rt_err_t rc ;
@@ -404,7 +533,7 @@ rt_err_t rt_backtrace_thread(rt_thread_t thread)
404
533
rc = rt_hw_backtrace_frame_get (thread , & frame );
405
534
if (rc == RT_EOK )
406
535
{
407
- rc = rt_backtrace_frame (& frame );
536
+ rc = rt_backtrace_frame (thread , & frame );
408
537
}
409
538
}
410
539
else
@@ -643,7 +772,14 @@ rt_inline void _slab_info(rt_size_t *total,
643
772
#define _MEM_INFO (...)
644
773
#endif
645
774
646
- static void _rt_system_heap_init (void * begin_addr , void * end_addr )
775
+ /**
776
+ * @brief This function will do the generic system heap initialization.
777
+ *
778
+ * @param begin_addr the beginning address of system page.
779
+ *
780
+ * @param end_addr the end address of system page.
781
+ */
782
+ void rt_system_heap_init_generic (void * begin_addr , void * end_addr )
647
783
{
648
784
rt_ubase_t begin_align = RT_ALIGN ((rt_ubase_t )begin_addr , RT_ALIGN_SIZE );
649
785
rt_ubase_t end_align = RT_ALIGN_DOWN ((rt_ubase_t )end_addr , RT_ALIGN_SIZE );
@@ -657,15 +793,16 @@ static void _rt_system_heap_init(void *begin_addr, void *end_addr)
657
793
}
658
794
659
795
/**
660
- * @brief This function will init system heap.
796
+ * @brief This function will init system heap. User can override this API to
797
+ * complete other works, like heap sanitizer initialization.
661
798
*
662
799
* @param begin_addr the beginning address of system page.
663
800
*
664
801
* @param end_addr the end address of system page.
665
802
*/
666
803
rt_weak void rt_system_heap_init (void * begin_addr , void * end_addr )
667
804
{
668
- _rt_system_heap_init (begin_addr , end_addr );
805
+ rt_system_heap_init_generic (begin_addr , end_addr );
669
806
}
670
807
671
808
/**
0 commit comments