• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "los_backtrace.h"
33 #include "los_task.h"
34 #include "los_debug.h"
35 #if (LOSCFG_BACKTRACE_TYPE == 4)
36 #include "los_arch_regs.h"
37 #endif
38 
39 #if (LOSCFG_BACKTRACE_TYPE != 0)
40 /* This function is used to judge whether the data in the stack is a code section address.
41    The default code section is only one, but there may be more than one. Modify the
42    judgment condition to support multiple code sections. */
OsStackDataIsCodeAddr(UINTPTR value)43 WEAK BOOL OsStackDataIsCodeAddr(UINTPTR value)
44 {
45     if ((value >= CODE_START_ADDR) && (value < CODE_END_ADDR)) {
46         return TRUE;
47     }
48     return FALSE;
49 }
50 
51 #if (LOSCFG_BACKTRACE_TYPE == 1)
52 #define OS_BACKTRACE_START     2
53 /* Thumb instruction, so the pc must be an odd number */
54 #define OS_IS_THUMB_INSTRUCTION(pc)    ((pc & 0x1) == 1)
55 
56 /* BL or BLX instruction flag. */
57 #define OS_BL_INS_MASK     0xF800
58 #define OS_BL_INS_HIGH     0xF800
59 #define OS_BL_INS_LOW      0xF000
60 #define OS_BLX_INX_MASK    0xFF00
61 #define OS_BLX_INX         0x4700
62 
63 #if defined(__ICCARM__) || defined(__CC_ARM)
HalSpGet(VOID)64 STATIC INLINE UINTPTR HalSpGet(VOID)
65 {
66     UINTPTR sp;
67     __asm("mov %0, sp" : "=r" (sp));
68     return sp;
69 }
70 
HalPspGet(VOID)71 STATIC INLINE UINTPTR HalPspGet(VOID)
72 {
73     UINTPTR psp;
74     __asm("mrs %0, psp" : "=r" (psp));
75     return psp;
76 }
77 
HalMspGet(VOID)78 STATIC INLINE UINTPTR HalMspGet(VOID)
79 {
80     UINTPTR msp;
81     __asm("mrs %0, msp" : "=r" (msp));
82     return msp;
83 }
84 #elif defined(__CLANG_ARM) || defined(__GNUC__)
HalSpGet(VOID)85 STATIC INLINE UINTPTR HalSpGet(VOID)
86 {
87     UINTPTR sp;
88     __asm volatile("mov %0, sp" : "=r" (sp));
89     return sp;
90 }
91 
HalPspGet(VOID)92 STATIC INLINE UINTPTR HalPspGet(VOID)
93 {
94     UINTPTR psp;
95     __asm volatile("mrs %0, psp" : "=r" (psp));
96     return psp;
97 }
98 
HalMspGet(VOID)99 STATIC INLINE UINTPTR HalMspGet(VOID)
100 {
101     UINTPTR msp;
102     __asm volatile("mrs %0, msp" : "=r" (msp));
103     return msp;
104 }
105 #else
106 #error Unknown compiler.
107 #endif
108 
OsInsIsBlOrBlx(UINTPTR addr)109 STATIC INLINE BOOL OsInsIsBlOrBlx(UINTPTR addr)
110 {
111     UINT16 ins1 = *((UINT16 *)addr);
112     UINT16 ins2 = *((UINT16 *)(addr + 2)); /* 2: Thumb instruction is two bytes. */
113 
114     if (((ins2 & OS_BL_INS_MASK) == OS_BL_INS_HIGH) &&
115         ((ins1 & OS_BL_INS_MASK) == OS_BL_INS_LOW)) {
116         return TRUE;
117     } else if ((ins2 & OS_BLX_INX_MASK) == OS_BLX_INX) {
118         return TRUE;
119     } else {
120         return FALSE;
121     }
122 }
123 
OsStackAddrGet(UINTPTR * stackStart,UINTPTR * stackEnd,UINTPTR SP)124 STATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINTPTR SP)
125 {
126     if (SP != 0) {
127         *stackStart = SP;
128         if ((SP >= CSTACK_START_ADDR) && (SP < CSTACK_END_ADDR)) {
129             *stackEnd = CSTACK_END_ADDR;
130         } else {
131             UINT32 taskID = LOS_CurTaskIDGet();
132             LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
133             *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize;
134             if ((SP < (UINTPTR)taskCB->topOfStack) || (SP >= *stackEnd)) {
135                 PRINT_ERR("msp statck [0x%x, 0x%x], cur task stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n",
136                           CSTACK_START_ADDR, CSTACK_END_ADDR, (UINTPTR)taskCB->topOfStack, *stackEnd, SP);
137                 return LOS_NOK;
138             }
139         }
140     } else {
141         if (HalSpGet() != HalPspGet()) {
142             *stackStart = HalMspGet();
143             *stackEnd = CSTACK_END_ADDR;
144             if ((*stackStart < CSTACK_START_ADDR) || (*stackStart >= CSTACK_END_ADDR)) {
145                 PRINT_ERR("msp stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n",
146                           CSTACK_START_ADDR, CSTACK_END_ADDR, *stackStart);
147                 return LOS_NOK;
148             }
149             PRINTK("msp, start = %x, end = %x\n", *stackStart, *stackEnd);
150         } else {
151             *stackStart = HalPspGet();
152             UINT32 taskID = LOS_CurTaskIDGet();
153             LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
154             *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize;
155             if ((*stackStart < (UINTPTR)taskCB->topOfStack) || (*stackStart >= *stackEnd)) {
156                 PRINT_ERR("psp stack [0x%x, 0x%x], cur sp(0x%x) is overflow, cur task id is %d!\n",
157                           taskCB->topOfStack, *stackEnd, *stackStart, taskID);
158                 return LOS_NOK;
159             }
160             PRINTK("psp, start = %x, end = %x\n", *stackStart, *stackEnd);
161         }
162     }
163 
164     return LOS_OK;
165 }
166 
OsAddrIsValid(UINTPTR sp)167 STATIC INLINE UINTPTR OsAddrIsValid(UINTPTR sp)
168 {
169     UINTPTR pc;
170     BOOL ret;
171 
172     /* The stack space pointed to by the current SP may store the LR,
173        so need decrease a word to PC. */
174     pc = *((UINTPTR *)sp) - sizeof(UINTPTR);
175 
176     if (!OS_IS_THUMB_INSTRUCTION(pc)) {
177         return 0;
178     }
179 
180     /* PC in thumb mode is an odd number, fix the PC address by decreasing one byte. */
181     pc = *((UINTPTR *)sp) - 1;
182 
183     ret = OsStackDataIsCodeAddr(pc);
184     if (ret == FALSE) {
185         return 0;
186     }
187 
188     ret = OsInsIsBlOrBlx(pc - sizeof(UINTPTR));
189     if (ret == FALSE) {
190         return 0;
191     }
192 
193     return pc;
194 }
195 #elif (LOSCFG_BACKTRACE_TYPE == 2)
196 #define OS_BACKTRACE_START     1
197 #define OS_RA_OFFSET           4
198 #define OS_FP_OFFSET           8
199 #define OS_FP_ALIGN(value)     (((UINT32)(value) & (UINT32)(LOSCFG_STACK_POINT_ALIGN_SIZE - 1)) == 0)
200 
OsFpGet(VOID)201 STATIC INLINE UINTPTR OsFpGet(VOID)
202 {
203     UINTPTR fp = 0;
204     __asm volatile("mv %0, s0" : "=r"(fp));
205     dsb();
206     return fp;
207 }
208 
IsValidFP(UINTPTR fp)209 WEAK BOOL IsValidFP(UINTPTR fp)
210 {
211     LosTaskCB *taskCB = NULL;
212     UINTPTR stackTop, stackBottom;
213     UINTPTR irqStackTop, irqStackBottom;
214 
215     if ((fp == FP_INIT_VALUE) || !OS_FP_ALIGN(fp)) {
216         return FALSE;
217     }
218 
219     if (LOS_TaskIsRunning()) {
220         taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
221         stackTop = taskCB->topOfStack;
222         stackBottom = taskCB->topOfStack + taskCB->stackSize;
223         irqStackTop = (UINTPTR)CSTACK_START_ADDR;
224         irqStackBottom = (UINTPTR)CSTACK_SECTION_END;
225     } else {
226         stackTop = 0;
227         stackBottom = 0;
228         irqStackTop = (UINTPTR)CSTACK_START_ADDR;
229         irqStackBottom = (UINTPTR)CSTACK_SECTION_END;
230     }
231 
232     if (((fp > stackTop) && (fp <= stackBottom)) || ((fp > irqStackTop) && (fp <= irqStackBottom))) {
233         return TRUE;
234     }
235 
236     return FALSE;
237 }
238 
LOS_RecordLR(UINTPTR * LR,UINT32 LRSize,UINT32 jumpCount,UINTPTR SP)239 VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
240 {
241     UINTPTR backFp;
242     UINTPTR tmpFp;
243     UINTPTR backRa;
244     UINT32 count = 0;
245     UINT32 index = 0;
246 
247     if (LR == NULL) {
248         return;
249     }
250 
251     if (SP != 0) {
252         backFp = SP;
253     } else {
254         backFp = OsFpGet();
255     }
256 
257     if (!IsValidFP(backFp)) {
258         PRINT_ERR("BackTrace failed! Invalid fp 0x%x\n", backFp);
259         return;
260     }
261 
262     do {
263         tmpFp = backFp;
264         backRa = *((UINTPTR *)(UINTPTR)(tmpFp - OS_RA_OFFSET));
265         backFp = *((UINTPTR *)(UINTPTR)(tmpFp - OS_FP_OFFSET));
266         if (index++ < jumpCount) {
267             continue;
268         }
269 
270         LR[count] = backRa;
271         count++;
272         if ((count == LRSize) || (backFp == tmpFp)) {
273             break;
274         }
275     } while (IsValidFP(backFp));
276 
277     if (count < LRSize) {
278         LR[count] = 0;
279     }
280 }
281 #elif (LOSCFG_BACKTRACE_TYPE == 3)
282 #define OS_BACKTRACE_START  1
283 #define OS_JALX_INS_MASK    0x7F
284 #define OS_JAL_INS_LOW      0x6F
285 #define OS_JAL_16_INS_MASK  0x2001
286 #define OS_JALR_INS_LOW     0x67
287 #define OS_JALR_16_INS_MASK 0x9002
288 #define OS_JR_16_INS_MASK   0x8002
289 #define OS_J_16_INS_MASK    0xA001
290 
OsInsIsJump(UINTPTR addr)291 STATIC INLINE BOOL OsInsIsJump(UINTPTR addr)
292 {
293     UINT16 ins1 = *((UINT16 *)addr);
294     UINT16 ins2 = *((UINT16 *)(addr + 2)); // 2, for the mask
295 
296     /* Jal ins */
297     if (((ins1 & OS_JALX_INS_MASK) == OS_JAL_INS_LOW) ||
298         ((ins1 & OS_JAL_16_INS_MASK) == OS_JAL_16_INS_MASK) ||
299         ((ins2 & OS_JAL_16_INS_MASK) == OS_JAL_16_INS_MASK)) {
300         return TRUE;
301     }
302 
303     /* Jalr ins */
304     if (((ins1 & OS_JALX_INS_MASK) == OS_JALR_INS_LOW) ||
305         ((ins1 & OS_JALR_16_INS_MASK) == OS_JALR_16_INS_MASK) ||
306         ((ins2 & OS_JALR_16_INS_MASK) == OS_JALR_16_INS_MASK)) {
307         return TRUE;
308     }
309 
310     /* Jr ins */
311     if (((ins1 & OS_JR_16_INS_MASK) == OS_JR_16_INS_MASK) ||
312         ((ins2 & OS_JR_16_INS_MASK) == OS_JR_16_INS_MASK)) {
313         return TRUE;
314     }
315 
316     /* J ins */
317     if (((ins1 & OS_J_16_INS_MASK) == OS_J_16_INS_MASK) ||
318         ((ins2 & OS_J_16_INS_MASK) == OS_J_16_INS_MASK)) {
319         return TRUE;
320     }
321 
322     return FALSE;
323 }
324 
OsSpGet(VOID)325 STATIC INLINE UINTPTR OsSpGet(VOID)
326 {
327     UINTPTR sp = 0;
328     __asm volatile("mv %0, sp" : "=r"(sp));
329     dsb();
330     return sp;
331 }
332 
OsStackAddrGet(UINTPTR * stackStart,UINTPTR * stackEnd,UINTPTR SP)333 STATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINTPTR SP)
334 {
335     if (SP != 0) {
336         *stackStart = SP;
337         if ((SP >= CSTACK_START_ADDR) && (SP < CSTACK_END_ADDR)) {
338             *stackEnd = CSTACK_END_ADDR;
339         } else {
340             UINT32 taskID = LOS_CurTaskIDGet();
341             LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
342             *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize;
343             if ((SP < (UINTPTR)taskCB->topOfStack) || (SP >= *stackEnd)) {
344                 PRINT_ERR("msp statck [0x%x, 0x%x], cur task stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n",
345                           CSTACK_START_ADDR, CSTACK_END_ADDR, (UINTPTR)taskCB->topOfStack, *stackEnd, SP);
346                 return LOS_NOK;
347             }
348         }
349     } else {
350         if (!LOS_TaskIsRunning()) {
351             *stackStart = OsSpGet();
352             *stackEnd = CSTACK_END_ADDR;
353             if ((*stackStart < CSTACK_START_ADDR) || (*stackStart >= CSTACK_END_ADDR)) {
354                 PRINT_ERR("msp stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n",
355                           CSTACK_START_ADDR, CSTACK_END_ADDR, *stackStart);
356                 return LOS_NOK;
357             }
358         } else {
359             *stackStart = OsSpGet();
360             UINT32 taskID = LOS_CurTaskIDGet();
361             LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
362             *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize;
363             if ((*stackStart < (UINTPTR)taskCB->topOfStack) || (*stackStart >= *stackEnd)) {
364                 PRINT_ERR("psp stack [0x%x, 0x%x], cur sp(0x%x) is overflow, cur task id is %d!\n",
365                           taskCB->topOfStack, *stackEnd, *stackStart, taskID);
366                 return LOS_NOK;
367             }
368         }
369     }
370 
371     return LOS_OK;
372 }
373 
OsAddrIsValid(UINTPTR sp)374 STATIC INLINE UINTPTR OsAddrIsValid(UINTPTR sp)
375 {
376     UINTPTR pc;
377     BOOL ret;
378 
379     pc = *((UINTPTR *)sp);
380 
381     ret = OsStackDataIsCodeAddr(pc);
382     if (ret == FALSE) {
383         return 0;
384     }
385 
386     ret = OsInsIsJump(pc - sizeof(UINTPTR));
387     if (ret == FALSE) {
388         return 0;
389     }
390 
391     return pc;
392 }
393 
394 #elif (LOSCFG_BACKTRACE_TYPE == 4)
395 #define OS_BACKTRACE_START     0
396 #define ALIGN_MASK             (4 - 1)
397 #define OS_REG_LR_OFFSET       (CONTEXT_SIZE - 8)
398 
IsSpAligned(UINT32 value)399 UINT32 IsSpAligned(UINT32 value)
400 {
401     return (value & (UINT32)(ALIGN_MASK)) == 0;
402 }
403 
HalGetLr(VOID)404 STATIC INLINE UINTPTR HalGetLr(VOID)
405 {
406     UINTPTR regLr;
407 
408     __asm__ __volatile__("mov %0, a0" : "=r"(regLr));
409 
410     return regLr;
411 }
412 
413 /* This function is used to check sp address. */
IsValidSP(UINTPTR regSP,UINTPTR start,UINTPTR end)414 BOOL IsValidSP(UINTPTR regSP, UINTPTR start, UINTPTR end)
415 {
416     return (regSP >= start) && (regSP <= end) && IsSpAligned(regSP);
417 }
418 
419 /* This function is used to check return address. */
IsValidRa(UINTPTR regRA)420 BOOL IsValidRa(UINTPTR regRA)
421 {
422     regRA &= ~VIR_TEXT_ADDR_MASK;
423     regRA |= TEXT_ADDR_MASK;
424 
425     return OsStackDataIsCodeAddr(regRA);
426 }
427 
FindSuitableStack(UINTPTR regSP,UINTPTR * start,UINTPTR * end)428 BOOL FindSuitableStack(UINTPTR regSP, UINTPTR *start, UINTPTR *end)
429 {
430     UINT32 stackStart;
431     UINT32 stackEnd;
432     BOOL found = FALSE;
433 
434     if (LOS_TaskIsRunning()) {
435         UINT32 taskID = LOS_CurTaskIDGet();
436         LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
437         stackStart = taskCB->topOfStack;
438         stackEnd = taskCB->topOfStack + taskCB->stackSize;
439         if (IsValidSP(regSP, stackStart, stackEnd)) {
440             found = TRUE;
441             goto FOUND;
442         }
443     }
444 
445     if (IsValidSP(regSP, CSTACK_START_ADDR, CSTACK_END_ADDR)) {
446         stackStart = CSTACK_START_ADDR;
447         stackEnd = CSTACK_END_ADDR;
448         found = TRUE;
449         goto FOUND;
450     }
451 
452 FOUND:
453     if (found == TRUE) {
454         *start = stackStart;
455         *end = stackEnd;
456     }
457 
458     return found;
459 }
460 
HalBackTraceGet(UINTPTR sp,UINT32 retAddr,UINTPTR * callChain,UINT32 maxDepth,UINT32 jumpCount)461 UINT32 HalBackTraceGet(UINTPTR sp, UINT32 retAddr, UINTPTR *callChain, UINT32 maxDepth, UINT32 jumpCount)
462 {
463     UINTPTR tmpSp;
464     UINT32 tmpRa;
465     UINTPTR backRa = retAddr;
466     UINTPTR backSp = sp;
467     UINTPTR stackStart;
468     UINT32 stackEnd;
469     UINT32 count = 0;
470     UINT32 index = 0;
471 
472     if (FindSuitableStack(sp, &stackStart, &stackEnd) == FALSE) {
473         PRINTK("sp:0x%x error, backtrace failed!\n", sp);
474         return 0;
475     }
476 
477     while (IsValidSP(backSp, stackStart, stackEnd)) {
478         if (callChain == NULL) {
479             PRINTK("trace%u  ra:0x%x  sp:0x%x\n", count, (backRa << WINDOW_INCREMENT_SHIFT) >>
480                     WINDOW_INCREMENT_SHIFT, backSp);
481         } else {
482             if (index++ < jumpCount) {
483                 continue;
484             }
485             backRa &= ~VIR_TEXT_ADDR_MASK;
486             backRa |= TEXT_ADDR_MASK;
487             callChain[count++] = backRa;
488         }
489 
490         tmpRa = backRa;
491         tmpSp = backSp;
492         backRa = *((UINT32 *)(UINTPTR)(tmpSp - RA_OFFSET));
493         backSp = *((UINT32 *)(UINTPTR)(tmpSp - SP_OFFSET));
494 
495         if ((tmpRa == backRa) || (backSp == tmpSp) || (count == maxDepth) || !IsValidRa(backRa)) {
496             break;
497         }
498     }
499 
500     return count;
501 }
502 
LOS_RecordLR(UINTPTR * LR,UINT32 LRSize,UINT32 jumpCount,UINTPTR SP)503 VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
504 {
505     UINTPTR reglr;
506     if (LR == NULL) {
507         return;
508     }
509 
510     if (SP == 0) {
511         __asm__ __volatile__("mov %0, sp" : "=a"(SP) : :);
512         __asm__ __volatile__("mov %0, a0" : "=a"(reglr) : :);
513     } else {
514         reglr = *(UINT32 *)(SP - OS_REG_LR_OFFSET);
515     }
516     HakSpillWindow();
517     HalBackTraceGet(SP, reglr, LR, LRSize, jumpCount);
518 }
519 #elif (LOSCFG_BACKTRACE_TYPE == 5)
520 #define OS_BACKTRACE_START     0
521 
IsAligned(UINT32 val,UINT32 align)522 UINT32 IsAligned(UINT32 val, UINT32 align)
523 {
524     return ((val & (align - 1)) == 0);
525 }
526 
OsSpGet(VOID)527 STATIC INLINE UINTPTR OsSpGet(VOID)
528 {
529     UINTPTR regSp;
530 
531     __asm__ __volatile__("mov %0, sp" : "=r"(regSp));
532 
533     return regSp;
534 }
535 
536 /* This function is used to check sp. */
IsValidSP(UINTPTR regSP,UINTPTR start,UINTPTR end)537 BOOL IsValidSP(UINTPTR regSP, UINTPTR start, UINTPTR end)
538 {
539     return (regSP >= start) && (regSP <= end);
540 }
541 
FindSuitableStack(UINTPTR regSP,UINTPTR * start,UINTPTR * end)542 BOOL FindSuitableStack(UINTPTR regSP, UINTPTR *start, UINTPTR *end)
543 {
544     UINT32 stackStart;
545     UINT32 stackEnd;
546     BOOL found = FALSE;
547 
548     if (LOS_TaskIsRunning()) {
549         UINT32 taskID = LOS_CurTaskIDGet();
550         LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
551         stackStart = taskCB->topOfStack;
552         stackEnd = taskCB->topOfStack + taskCB->stackSize;
553         if (IsValidSP(regSP, stackStart, stackEnd)) {
554             found = TRUE;
555             goto FOUND;
556         }
557     }
558 
559     if (IsValidSP(regSP, CSTACK_START_ADDR, CSTACK_END_ADDR)) {
560         stackStart = CSTACK_START_ADDR;
561         stackEnd = CSTACK_END_ADDR;
562         found = TRUE;
563         goto FOUND;
564     }
565 
566 FOUND:
567     if (found == TRUE) {
568         *start = stackStart;
569         *end = stackEnd;
570     }
571 
572     return found;
573 }
574 
LOS_RecordLR(UINTPTR * LR,UINT32 LRSize,UINT32 jumpCount,UINTPTR SP)575 VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
576 {
577     UINTPTR stackPointer;
578     UINTPTR topOfStack;
579     UINTPTR tmpStack = 0;
580     UINTPTR stackBottom;
581     UINTPTR checkBL;
582     UINT32 count = 0;
583     UINT32 index = 0;
584 
585     if (LR == NULL) {
586         return;
587     }
588 
589     if (SP == 0) {
590         SP = OsSpGet();
591     }
592 
593     stackPointer = SP;
594 
595     if (FindSuitableStack(stackPointer, &topOfStack, &stackBottom) == FALSE) {
596         return;
597     }
598 
599     while ((stackPointer < stackBottom) && (count < LRSize)) {
600         if (IsValidSP(*(UINT32 *)stackPointer, topOfStack, stackBottom)
601             && OsStackDataIsCodeAddr(*(UINT32 *)(stackPointer + STACK_OFFSET))
602             && IsAligned(*(UINT32 *)stackPointer, ALGIN_CODE)) {
603             if (tmpStack == *(UINT32 *)stackPointer) {
604                 break;
605             }
606             tmpStack = *(UINT32 *)stackPointer;
607             checkBL = *(UINT32 *)(stackPointer + STACK_OFFSET);
608             if (count++ < jumpCount) {
609                 continue;
610             }
611             stackPointer = tmpStack;
612             LR[index++] =  checkBL;
613             continue;
614         }
615         stackPointer += STACK_OFFSET;
616     }
617 
618     if (index < LRSize) {
619         LR[index] = 0;
620     }
621 }
622 #elif (LOSCFG_BACKTRACE_TYPE == 6)
623 #define OS_BACKTRACE_START               1
624 #define STACK_OFFSET                     4
625 #define THUMB_OFFSET                     2
626 #define THUMB_BIT                        16
627 #define ARM_ALIGN_CODE                   4
628 #define THUMB_ALIGN_CODE                 2
629 #define BL_CMD_OFFSET                    4
630 #define ARM_BL_MASK                      0xEB000000
631 #define THUMB_BL_MASK                    0xF000F000
632 #define CLEAR_LOW_BIT_MASK               0xFFFFFFFE
633 
IsAligned(UINT32 val,UINT32 align)634 STATIC INLINE BOOL IsAligned(UINT32 val, UINT32 align)
635 {
636     return ((val & (align - 1)) == 0);
637 }
638 
OsSpGet(VOID)639 STATIC INLINE UINTPTR OsSpGet(VOID)
640 {
641     UINTPTR SP;
642     __asm volatile("mov %0, sp" : "=r"(SP));
643     return SP;
644 }
645 
IsArmValidLr(UINTPTR lr)646 STATIC INLINE BOOL IsArmValidLr(UINTPTR lr)
647 {
648     return ((*(UINT32 *)(lr - BL_CMD_OFFSET) & ARM_BL_MASK) == ARM_BL_MASK);
649 }
650 
IsThumbValidLr(UINTPTR lr)651 STATIC INLINE BOOL IsThumbValidLr(UINTPTR lr)
652 {
653     lr = (*(UINT16 *)(lr - BL_CMD_OFFSET) << THUMB_BIT) + *(UINT16 *)(lr - THUMB_OFFSET);
654     return ((lr & THUMB_BL_MASK) == THUMB_BL_MASK);
655 }
656 
LOS_RecordLR(UINTPTR * LR,UINT32 LRSize,UINT32 jumpCount,UINTPTR SP)657 VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
658 {
659     UINT32 count = 0;
660     UINT32 index = 0;
661     LosTaskCB *taskCB = NULL;
662     UINT32 taskID;
663     UINT32 stackStart, stackEnd;
664     UINTPTR framePtr, tmpFramePtr, linkReg;
665 
666     if (LR == NULL) {
667         return;
668     }
669 
670     if (SP == 0) {
671         SP = OsSpGet();
672     }
673 
674     if (LOS_TaskIsRunning()) {
675         taskID = LOS_CurTaskIDGet();
676         taskCB = OS_TCB_FROM_TID(taskID);
677         stackStart = taskCB->topOfStack;
678         stackEnd = stackStart + taskCB->stackSize;
679     } else {
680         stackStart = CSTACK_START_ADDR;
681         stackEnd = CSTACK_END_ADDR;
682     }
683 
684     while ((SP > stackStart) && (SP < stackEnd)) {
685         linkReg = *(UINTPTR *)SP;
686         if (!OsStackDataIsCodeAddr(linkReg)) {
687             SP += STACK_OFFSET;
688             continue;
689         }
690         if (((!IsAligned(linkReg, ARM_ALIGN_CODE)) || !IsArmValidLr(linkReg)) &&
691             ((!IsAligned(linkReg - 1, THUMB_ALIGN_CODE)) || !IsThumbValidLr(linkReg - 1))) {
692             SP += STACK_OFFSET;
693             continue;
694         }
695         if (index >= jumpCount) {
696             LR[count++] = linkReg & CLEAR_LOW_BIT_MASK;
697             if (count == LRSize) {
698                 break;
699             }
700         }
701         ++index;
702         SP += STACK_OFFSET;
703     }
704 
705     /* if linkReg is not enough,clean up the last of the effective LR as the end. */
706     if (count < LRSize) {
707         LR[count] = 0;
708     }
709 }
710 #else
711 #error Unknown backtrace type.
712 #endif
713 
714 #if (LOSCFG_BACKTRACE_TYPE == 1) || (LOSCFG_BACKTRACE_TYPE == 3)
LOS_RecordLR(UINTPTR * LR,UINT32 LRSize,UINT32 jumpCount,UINTPTR SP)715 VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
716 {
717     if (LR == NULL) {
718         return;
719     }
720 
721     UINTPTR stackStart;
722     UINTPTR stackEnd;
723     UINT32 count = 0;
724     UINT32 index = 0;
725     UINTPTR sp;
726     UINTPTR pc;
727     UINT32 ret;
728 
729     ret = OsStackAddrGet(&stackStart, &stackEnd, SP);
730     if (ret != LOS_OK) {
731         return;
732     }
733 
734     /* Traverse the stack space and find the LR address. */
735     for (sp = stackStart; sp < stackEnd; sp += sizeof(UINTPTR)) {
736         pc = OsAddrIsValid(sp);
737         if ((pc != 0) && (count < LRSize)) {
738             if (index++ < jumpCount) {
739                 continue;
740             }
741             LR[count] = pc;
742             count++;
743             if (count == LRSize) {
744                 break;
745             }
746         }
747     }
748 
749     if (count < LRSize) {
750         LR[count] = 0;
751     }
752 }
753 #endif
754 
LOS_BackTrace(VOID)755 VOID LOS_BackTrace(VOID)
756 {
757     UINTPTR LR[BACKTRACE_MAX_DEPTH] = {0};
758     UINT32 index;
759 
760     LOS_RecordLR(LR, BACKTRACE_MAX_DEPTH, OS_BACKTRACE_START, 0);
761 
762     if (LOS_TaskIsRunning()) {
763         PRINTK("taskName = %s\n", g_losTask.runTask->taskName);
764         PRINTK("taskID   = %u\n", g_losTask.runTask->taskID);
765     }
766 
767     PRINTK("----- traceback start -----\r\n");
768     for (index = 0; index < BACKTRACE_MAX_DEPTH; index++) {
769         if (LR[index] == 0) {
770             break;
771         }
772         PRINTK("traceback %d -- lr = 0x%x\r\n", index, LR[index]);
773     }
774     PRINTK("----- traceback end -----\r\n");
775 }
776 
OsBackTraceInit(VOID)777 VOID OsBackTraceInit(VOID)
778 {
779     OsBackTraceHookSet(LOS_RecordLR);
780 }
781 #endif
782 
783