13d8536b4Sopenharmony_ci/*
23d8536b4Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
33d8536b4Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
43d8536b4Sopenharmony_ci *
53d8536b4Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
63d8536b4Sopenharmony_ci * are permitted provided that the following conditions are met:
73d8536b4Sopenharmony_ci *
83d8536b4Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
93d8536b4Sopenharmony_ci *    conditions and the following disclaimer.
103d8536b4Sopenharmony_ci *
113d8536b4Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
123d8536b4Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
133d8536b4Sopenharmony_ci *    provided with the distribution.
143d8536b4Sopenharmony_ci *
153d8536b4Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
163d8536b4Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
173d8536b4Sopenharmony_ci *    permission.
183d8536b4Sopenharmony_ci *
193d8536b4Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
203d8536b4Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
213d8536b4Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
223d8536b4Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
233d8536b4Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
243d8536b4Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
253d8536b4Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
263d8536b4Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
273d8536b4Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
283d8536b4Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
293d8536b4Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
303d8536b4Sopenharmony_ci */
313d8536b4Sopenharmony_ci
323d8536b4Sopenharmony_ci#include "los_backtrace.h"
333d8536b4Sopenharmony_ci#include "los_task.h"
343d8536b4Sopenharmony_ci#include "los_debug.h"
353d8536b4Sopenharmony_ci#include "los_arch.h"
363d8536b4Sopenharmony_ci#if (LOSCFG_BACKTRACE_TYPE == 4)
373d8536b4Sopenharmony_ci#include "los_arch_regs.h"
383d8536b4Sopenharmony_ci#endif
393d8536b4Sopenharmony_ci
403d8536b4Sopenharmony_ci#if (LOSCFG_BACKTRACE_TYPE != 0)
413d8536b4Sopenharmony_ci/* This function is used to judge whether the data in the stack is a code section address.
423d8536b4Sopenharmony_ci   The default code section is only one, but there may be more than one. Modify the
433d8536b4Sopenharmony_ci   judgment condition to support multiple code sections. */
443d8536b4Sopenharmony_ciWEAK BOOL OsStackDataIsCodeAddr(UINTPTR value)
453d8536b4Sopenharmony_ci{
463d8536b4Sopenharmony_ci    if ((value > CODE_START_ADDR) && (value < CODE_END_ADDR)) {
473d8536b4Sopenharmony_ci        return TRUE;
483d8536b4Sopenharmony_ci    }
493d8536b4Sopenharmony_ci    return FALSE;
503d8536b4Sopenharmony_ci}
513d8536b4Sopenharmony_ci
523d8536b4Sopenharmony_ci#if (LOSCFG_BACKTRACE_TYPE == 1)
533d8536b4Sopenharmony_ci#define OS_BACKTRACE_START     2
543d8536b4Sopenharmony_ci/* Thumb instruction, so the pc must be an odd number */
553d8536b4Sopenharmony_ci#define OS_IS_THUMB_INSTRUCTION(pc)    ((pc & 0x1) == 1)
563d8536b4Sopenharmony_ci
573d8536b4Sopenharmony_ci/* BL or BLX instruction flag. */
583d8536b4Sopenharmony_ci#define OS_BL_INS_MASK     0xF800
593d8536b4Sopenharmony_ci#define OS_BL_INS_HIGH     0xF800
603d8536b4Sopenharmony_ci#define OS_BL_INS_LOW      0xF000
613d8536b4Sopenharmony_ci#define OS_BLX_INX_MASK    0xFF00
623d8536b4Sopenharmony_ci#define OS_BLX_INX         0x4700
633d8536b4Sopenharmony_ci
643d8536b4Sopenharmony_ciSTATIC INLINE BOOL OsInsIsBlOrBlx(UINTPTR addr)
653d8536b4Sopenharmony_ci{
663d8536b4Sopenharmony_ci    UINT16 ins1 = *((UINT16 *)addr);
673d8536b4Sopenharmony_ci    UINT16 ins2 = *((UINT16 *)(addr + 2)); /* 2: Thumb instruction is two bytes. */
683d8536b4Sopenharmony_ci
693d8536b4Sopenharmony_ci    if (((ins2 & OS_BL_INS_MASK) == OS_BL_INS_HIGH) &&
703d8536b4Sopenharmony_ci        ((ins1 & OS_BL_INS_MASK) == OS_BL_INS_LOW)) {
713d8536b4Sopenharmony_ci        return TRUE;
723d8536b4Sopenharmony_ci    } else if ((ins2 & OS_BLX_INX_MASK) == OS_BLX_INX) {
733d8536b4Sopenharmony_ci        return TRUE;
743d8536b4Sopenharmony_ci    } else {
753d8536b4Sopenharmony_ci        return FALSE;
763d8536b4Sopenharmony_ci    }
773d8536b4Sopenharmony_ci}
783d8536b4Sopenharmony_ci
793d8536b4Sopenharmony_ciSTATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINTPTR SP)
803d8536b4Sopenharmony_ci{
813d8536b4Sopenharmony_ci    if (SP != 0) {
823d8536b4Sopenharmony_ci        *stackStart = SP;
833d8536b4Sopenharmony_ci        if ((SP >= CSTACK_START_ADDR) && (SP < CSTACK_END_ADDR)) {
843d8536b4Sopenharmony_ci            *stackEnd = CSTACK_END_ADDR;
853d8536b4Sopenharmony_ci        } else {
863d8536b4Sopenharmony_ci            UINT32 taskID = LOS_CurTaskIDGet();
873d8536b4Sopenharmony_ci            LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
883d8536b4Sopenharmony_ci            *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize;
893d8536b4Sopenharmony_ci            if ((SP < (UINTPTR)taskCB->topOfStack) || (SP >= *stackEnd)) {
903d8536b4Sopenharmony_ci                PRINT_ERR("msp statck [0x%x, 0x%x], cur task stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n",
913d8536b4Sopenharmony_ci                          CSTACK_START_ADDR, CSTACK_END_ADDR, (UINTPTR)taskCB->topOfStack, *stackEnd, SP);
923d8536b4Sopenharmony_ci                return LOS_NOK;
933d8536b4Sopenharmony_ci            }
943d8536b4Sopenharmony_ci        }
953d8536b4Sopenharmony_ci    } else {
963d8536b4Sopenharmony_ci        if (ArchSpGet() != ArchPspGet()) {
973d8536b4Sopenharmony_ci            *stackStart = ArchMspGet();
983d8536b4Sopenharmony_ci            *stackEnd = CSTACK_END_ADDR;
993d8536b4Sopenharmony_ci            if ((*stackStart < CSTACK_START_ADDR) || (*stackStart >= CSTACK_END_ADDR)) {
1003d8536b4Sopenharmony_ci                PRINT_ERR("msp stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n",
1013d8536b4Sopenharmony_ci                          CSTACK_START_ADDR, CSTACK_END_ADDR, *stackStart);
1023d8536b4Sopenharmony_ci                return LOS_NOK;
1033d8536b4Sopenharmony_ci            }
1043d8536b4Sopenharmony_ci            PRINTK("msp, start = %x, end = %x\n", *stackStart, *stackEnd);
1053d8536b4Sopenharmony_ci        } else {
1063d8536b4Sopenharmony_ci            *stackStart = ArchPspGet();
1073d8536b4Sopenharmony_ci            UINT32 taskID = LOS_CurTaskIDGet();
1083d8536b4Sopenharmony_ci            LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
1093d8536b4Sopenharmony_ci            *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize;
1103d8536b4Sopenharmony_ci            if ((*stackStart < (UINTPTR)taskCB->topOfStack) || (*stackStart >= *stackEnd)) {
1113d8536b4Sopenharmony_ci                PRINT_ERR("psp stack [0x%x, 0x%x], cur sp(0x%x) is overflow, cur task id is %d!\n",
1123d8536b4Sopenharmony_ci                          taskCB->topOfStack, *stackEnd, *stackStart, taskID);
1133d8536b4Sopenharmony_ci                return LOS_NOK;
1143d8536b4Sopenharmony_ci            }
1153d8536b4Sopenharmony_ci            PRINTK("psp, start = %x, end = %x\n", *stackStart, *stackEnd);
1163d8536b4Sopenharmony_ci        }
1173d8536b4Sopenharmony_ci    }
1183d8536b4Sopenharmony_ci
1193d8536b4Sopenharmony_ci    return LOS_OK;
1203d8536b4Sopenharmony_ci}
1213d8536b4Sopenharmony_ci
1223d8536b4Sopenharmony_ciSTATIC INLINE UINTPTR OsAddrIsValid(UINTPTR sp)
1233d8536b4Sopenharmony_ci{
1243d8536b4Sopenharmony_ci    UINTPTR pc;
1253d8536b4Sopenharmony_ci    BOOL ret;
1263d8536b4Sopenharmony_ci
1273d8536b4Sopenharmony_ci    /* The stack space pointed to by the current SP may store the LR,
1283d8536b4Sopenharmony_ci       so need decrease a word to PC. */
1293d8536b4Sopenharmony_ci    pc = *((UINTPTR *)sp) - sizeof(UINTPTR);
1303d8536b4Sopenharmony_ci
1313d8536b4Sopenharmony_ci    if (!OS_IS_THUMB_INSTRUCTION(pc)) {
1323d8536b4Sopenharmony_ci        return 0;
1333d8536b4Sopenharmony_ci    }
1343d8536b4Sopenharmony_ci
1353d8536b4Sopenharmony_ci    /* PC in thumb mode is an odd number, fix the PC address by decreasing one byte. */
1363d8536b4Sopenharmony_ci    pc = *((UINTPTR *)sp) - 1;
1373d8536b4Sopenharmony_ci
1383d8536b4Sopenharmony_ci    ret = OsStackDataIsCodeAddr(pc);
1393d8536b4Sopenharmony_ci    if (ret == FALSE) {
1403d8536b4Sopenharmony_ci        return 0;
1413d8536b4Sopenharmony_ci    }
1423d8536b4Sopenharmony_ci
1433d8536b4Sopenharmony_ci    ret = OsInsIsBlOrBlx(pc - sizeof(UINTPTR));
1443d8536b4Sopenharmony_ci    if (ret == FALSE) {
1453d8536b4Sopenharmony_ci        return 0;
1463d8536b4Sopenharmony_ci    }
1473d8536b4Sopenharmony_ci
1483d8536b4Sopenharmony_ci    return pc;
1493d8536b4Sopenharmony_ci}
1503d8536b4Sopenharmony_ci#elif (LOSCFG_BACKTRACE_TYPE == 2)
1513d8536b4Sopenharmony_ci#define OS_BACKTRACE_START     1
1523d8536b4Sopenharmony_ci#define OS_RA_OFFSET           4
1533d8536b4Sopenharmony_ci#define OS_FP_OFFSET           8
1543d8536b4Sopenharmony_ci#define OS_FP_ALIGN(value)     (((UINT32)(value) & (UINT32)(LOSCFG_STACK_POINT_ALIGN_SIZE - 1)) == 0)
1553d8536b4Sopenharmony_ci
1563d8536b4Sopenharmony_ciSTATIC INLINE UINTPTR OsFpGet(VOID)
1573d8536b4Sopenharmony_ci{
1583d8536b4Sopenharmony_ci    UINTPTR fp = 0;
1593d8536b4Sopenharmony_ci    __asm volatile("mv %0, s0" : "=r"(fp));
1603d8536b4Sopenharmony_ci    dsb();
1613d8536b4Sopenharmony_ci    return fp;
1623d8536b4Sopenharmony_ci}
1633d8536b4Sopenharmony_ci
1643d8536b4Sopenharmony_ciWEAK BOOL IsValidFP(UINTPTR fp)
1653d8536b4Sopenharmony_ci{
1663d8536b4Sopenharmony_ci    LosTaskCB *taskCB = NULL;
1673d8536b4Sopenharmony_ci    UINTPTR stackTop, stackBottom;
1683d8536b4Sopenharmony_ci    UINTPTR irqStackTop, irqStackBottom;
1693d8536b4Sopenharmony_ci
1703d8536b4Sopenharmony_ci    if ((fp == FP_INIT_VALUE) || !OS_FP_ALIGN(fp)) {
1713d8536b4Sopenharmony_ci        return FALSE;
1723d8536b4Sopenharmony_ci    }
1733d8536b4Sopenharmony_ci
1743d8536b4Sopenharmony_ci    if (LOS_TaskIsRunning()) {
1753d8536b4Sopenharmony_ci        taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
1763d8536b4Sopenharmony_ci        stackTop = taskCB->topOfStack;
1773d8536b4Sopenharmony_ci        stackBottom = taskCB->topOfStack + taskCB->stackSize;
1783d8536b4Sopenharmony_ci        irqStackTop = (UINTPTR)CSTACK_START_ADDR;
1793d8536b4Sopenharmony_ci        irqStackBottom = (UINTPTR)CSTACK_SECTION_END;
1803d8536b4Sopenharmony_ci    } else {
1813d8536b4Sopenharmony_ci        stackTop = 0;
1823d8536b4Sopenharmony_ci        stackBottom = 0;
1833d8536b4Sopenharmony_ci        irqStackTop = (UINTPTR)CSTACK_START_ADDR;
1843d8536b4Sopenharmony_ci        irqStackBottom = (UINTPTR)CSTACK_SECTION_END;
1853d8536b4Sopenharmony_ci    }
1863d8536b4Sopenharmony_ci
1873d8536b4Sopenharmony_ci    if (((fp > stackTop) && (fp <= stackBottom)) || ((fp > irqStackTop) && (fp <= irqStackBottom))) {
1883d8536b4Sopenharmony_ci        return TRUE;
1893d8536b4Sopenharmony_ci    }
1903d8536b4Sopenharmony_ci
1913d8536b4Sopenharmony_ci    return FALSE;
1923d8536b4Sopenharmony_ci}
1933d8536b4Sopenharmony_ci
1943d8536b4Sopenharmony_ciVOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
1953d8536b4Sopenharmony_ci{
1963d8536b4Sopenharmony_ci    UINTPTR backFp;
1973d8536b4Sopenharmony_ci    UINTPTR tmpFp;
1983d8536b4Sopenharmony_ci    UINTPTR backRa;
1993d8536b4Sopenharmony_ci    UINT32 count = 0;
2003d8536b4Sopenharmony_ci    UINT32 index = 0;
2013d8536b4Sopenharmony_ci
2023d8536b4Sopenharmony_ci    if (LR == NULL) {
2033d8536b4Sopenharmony_ci        return;
2043d8536b4Sopenharmony_ci    }
2053d8536b4Sopenharmony_ci
2063d8536b4Sopenharmony_ci    if (SP != 0) {
2073d8536b4Sopenharmony_ci        backFp = SP;
2083d8536b4Sopenharmony_ci    } else {
2093d8536b4Sopenharmony_ci        backFp = OsFpGet();
2103d8536b4Sopenharmony_ci    }
2113d8536b4Sopenharmony_ci
2123d8536b4Sopenharmony_ci    if (!IsValidFP(backFp)) {
2133d8536b4Sopenharmony_ci        PRINT_ERR("BackTrace failed! Invalid fp 0x%x\n", backFp);
2143d8536b4Sopenharmony_ci        return;
2153d8536b4Sopenharmony_ci    }
2163d8536b4Sopenharmony_ci
2173d8536b4Sopenharmony_ci    do {
2183d8536b4Sopenharmony_ci        tmpFp = backFp;
2193d8536b4Sopenharmony_ci        backRa = *((UINTPTR *)(UINTPTR)(tmpFp - OS_RA_OFFSET));
2203d8536b4Sopenharmony_ci        backFp = *((UINTPTR *)(UINTPTR)(tmpFp - OS_FP_OFFSET));
2213d8536b4Sopenharmony_ci        if (index++ < jumpCount) {
2223d8536b4Sopenharmony_ci            continue;
2233d8536b4Sopenharmony_ci        }
2243d8536b4Sopenharmony_ci
2253d8536b4Sopenharmony_ci        LR[count] = backRa;
2263d8536b4Sopenharmony_ci        count++;
2273d8536b4Sopenharmony_ci        if ((count == LRSize) || (backFp == tmpFp)) {
2283d8536b4Sopenharmony_ci            break;
2293d8536b4Sopenharmony_ci        }
2303d8536b4Sopenharmony_ci    } while (IsValidFP(backFp));
2313d8536b4Sopenharmony_ci
2323d8536b4Sopenharmony_ci    if (count < LRSize) {
2333d8536b4Sopenharmony_ci        LR[count] = 0;
2343d8536b4Sopenharmony_ci    }
2353d8536b4Sopenharmony_ci}
2363d8536b4Sopenharmony_ci#elif (LOSCFG_BACKTRACE_TYPE == 3)
2373d8536b4Sopenharmony_ci#define OS_BACKTRACE_START  1
2383d8536b4Sopenharmony_ci#define OS_JALX_INS_MASK    0x7F
2393d8536b4Sopenharmony_ci#define OS_JAL_INS_LOW      0x6F
2403d8536b4Sopenharmony_ci#define OS_JAL_16_INS_MASK  0x2001
2413d8536b4Sopenharmony_ci#define OS_JALR_INS_LOW     0x67
2423d8536b4Sopenharmony_ci#define OS_JALR_16_INS_MASK 0x9002
2433d8536b4Sopenharmony_ci#define OS_JR_16_INS_MASK   0x8002
2443d8536b4Sopenharmony_ci#define OS_J_16_INS_MASK    0xA001
2453d8536b4Sopenharmony_ci
2463d8536b4Sopenharmony_ciSTATIC INLINE BOOL OsInsIsJump(UINTPTR addr)
2473d8536b4Sopenharmony_ci{
2483d8536b4Sopenharmony_ci    UINT16 ins1 = *((UINT16 *)addr);
2493d8536b4Sopenharmony_ci    UINT16 ins2 = *((UINT16 *)(addr + 2)); // 2, for the mask
2503d8536b4Sopenharmony_ci
2513d8536b4Sopenharmony_ci    /* Jal ins */
2523d8536b4Sopenharmony_ci    if (((ins1 & OS_JALX_INS_MASK) == OS_JAL_INS_LOW) ||
2533d8536b4Sopenharmony_ci        ((ins1 & OS_JAL_16_INS_MASK) == OS_JAL_16_INS_MASK) ||
2543d8536b4Sopenharmony_ci        ((ins2 & OS_JAL_16_INS_MASK) == OS_JAL_16_INS_MASK)) {
2553d8536b4Sopenharmony_ci        return TRUE;
2563d8536b4Sopenharmony_ci    }
2573d8536b4Sopenharmony_ci
2583d8536b4Sopenharmony_ci    /* Jalr ins */
2593d8536b4Sopenharmony_ci    if (((ins1 & OS_JALX_INS_MASK) == OS_JALR_INS_LOW) ||
2603d8536b4Sopenharmony_ci        ((ins1 & OS_JALR_16_INS_MASK) == OS_JALR_16_INS_MASK) ||
2613d8536b4Sopenharmony_ci        ((ins2 & OS_JALR_16_INS_MASK) == OS_JALR_16_INS_MASK)) {
2623d8536b4Sopenharmony_ci        return TRUE;
2633d8536b4Sopenharmony_ci    }
2643d8536b4Sopenharmony_ci
2653d8536b4Sopenharmony_ci    /* Jr ins */
2663d8536b4Sopenharmony_ci    if (((ins1 & OS_JR_16_INS_MASK) == OS_JR_16_INS_MASK) ||
2673d8536b4Sopenharmony_ci        ((ins2 & OS_JR_16_INS_MASK) == OS_JR_16_INS_MASK)) {
2683d8536b4Sopenharmony_ci        return TRUE;
2693d8536b4Sopenharmony_ci    }
2703d8536b4Sopenharmony_ci
2713d8536b4Sopenharmony_ci    /* J ins */
2723d8536b4Sopenharmony_ci    if (((ins1 & OS_J_16_INS_MASK) == OS_J_16_INS_MASK) ||
2733d8536b4Sopenharmony_ci        ((ins2 & OS_J_16_INS_MASK) == OS_J_16_INS_MASK)) {
2743d8536b4Sopenharmony_ci        return TRUE;
2753d8536b4Sopenharmony_ci    }
2763d8536b4Sopenharmony_ci
2773d8536b4Sopenharmony_ci    return FALSE;
2783d8536b4Sopenharmony_ci}
2793d8536b4Sopenharmony_ci
2803d8536b4Sopenharmony_ciSTATIC INLINE UINTPTR OsSpGet(VOID)
2813d8536b4Sopenharmony_ci{
2823d8536b4Sopenharmony_ci    UINTPTR sp = 0;
2833d8536b4Sopenharmony_ci    __asm volatile("mv %0, sp" : "=r"(sp));
2843d8536b4Sopenharmony_ci    dsb();
2853d8536b4Sopenharmony_ci    return sp;
2863d8536b4Sopenharmony_ci}
2873d8536b4Sopenharmony_ci
2883d8536b4Sopenharmony_ciSTATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINTPTR SP)
2893d8536b4Sopenharmony_ci{
2903d8536b4Sopenharmony_ci    if (SP != 0) {
2913d8536b4Sopenharmony_ci        *stackStart = SP;
2923d8536b4Sopenharmony_ci        if ((SP >= CSTACK_START_ADDR) && (SP < CSTACK_END_ADDR)) {
2933d8536b4Sopenharmony_ci            *stackEnd = CSTACK_END_ADDR;
2943d8536b4Sopenharmony_ci        } else {
2953d8536b4Sopenharmony_ci            UINT32 taskID = LOS_CurTaskIDGet();
2963d8536b4Sopenharmony_ci            LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
2973d8536b4Sopenharmony_ci            *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize;
2983d8536b4Sopenharmony_ci            if ((SP < (UINTPTR)taskCB->topOfStack) || (SP >= *stackEnd)) {
2993d8536b4Sopenharmony_ci                PRINT_ERR("msp statck [0x%x, 0x%x], cur task stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n",
3003d8536b4Sopenharmony_ci                          CSTACK_START_ADDR, CSTACK_END_ADDR, (UINTPTR)taskCB->topOfStack, *stackEnd, SP);
3013d8536b4Sopenharmony_ci                return LOS_NOK;
3023d8536b4Sopenharmony_ci            }
3033d8536b4Sopenharmony_ci        }
3043d8536b4Sopenharmony_ci    } else {
3053d8536b4Sopenharmony_ci        if (!LOS_TaskIsRunning()) {
3063d8536b4Sopenharmony_ci            *stackStart = OsSpGet();
3073d8536b4Sopenharmony_ci            *stackEnd = CSTACK_END_ADDR;
3083d8536b4Sopenharmony_ci            if ((*stackStart < CSTACK_START_ADDR) || (*stackStart >= CSTACK_END_ADDR)) {
3093d8536b4Sopenharmony_ci                PRINT_ERR("msp stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n",
3103d8536b4Sopenharmony_ci                          CSTACK_START_ADDR, CSTACK_END_ADDR, *stackStart);
3113d8536b4Sopenharmony_ci                return LOS_NOK;
3123d8536b4Sopenharmony_ci            }
3133d8536b4Sopenharmony_ci        } else {
3143d8536b4Sopenharmony_ci            *stackStart = OsSpGet();
3153d8536b4Sopenharmony_ci            UINT32 taskID = LOS_CurTaskIDGet();
3163d8536b4Sopenharmony_ci            LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
3173d8536b4Sopenharmony_ci            *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize;
3183d8536b4Sopenharmony_ci            if ((*stackStart < (UINTPTR)taskCB->topOfStack) || (*stackStart >= *stackEnd)) {
3193d8536b4Sopenharmony_ci                PRINT_ERR("psp stack [0x%x, 0x%x], cur sp(0x%x) is overflow, cur task id is %d!\n",
3203d8536b4Sopenharmony_ci                          taskCB->topOfStack, *stackEnd, *stackStart, taskID);
3213d8536b4Sopenharmony_ci                return LOS_NOK;
3223d8536b4Sopenharmony_ci            }
3233d8536b4Sopenharmony_ci        }
3243d8536b4Sopenharmony_ci    }
3253d8536b4Sopenharmony_ci
3263d8536b4Sopenharmony_ci    return LOS_OK;
3273d8536b4Sopenharmony_ci}
3283d8536b4Sopenharmony_ci
3293d8536b4Sopenharmony_ciSTATIC INLINE UINTPTR OsAddrIsValid(UINTPTR sp)
3303d8536b4Sopenharmony_ci{
3313d8536b4Sopenharmony_ci    UINTPTR pc;
3323d8536b4Sopenharmony_ci    BOOL ret;
3333d8536b4Sopenharmony_ci
3343d8536b4Sopenharmony_ci    pc = *((UINTPTR *)sp);
3353d8536b4Sopenharmony_ci
3363d8536b4Sopenharmony_ci    ret = OsStackDataIsCodeAddr(pc);
3373d8536b4Sopenharmony_ci    if (ret == FALSE) {
3383d8536b4Sopenharmony_ci        return 0;
3393d8536b4Sopenharmony_ci    }
3403d8536b4Sopenharmony_ci
3413d8536b4Sopenharmony_ci    ret = OsInsIsJump(pc - sizeof(UINTPTR));
3423d8536b4Sopenharmony_ci    if (ret == FALSE) {
3433d8536b4Sopenharmony_ci        return 0;
3443d8536b4Sopenharmony_ci    }
3453d8536b4Sopenharmony_ci
3463d8536b4Sopenharmony_ci    return pc;
3473d8536b4Sopenharmony_ci}
3483d8536b4Sopenharmony_ci
3493d8536b4Sopenharmony_ci#elif (LOSCFG_BACKTRACE_TYPE == 4)
3503d8536b4Sopenharmony_ci#define OS_BACKTRACE_START     0
3513d8536b4Sopenharmony_ci#define ALIGN_MASK             (4 - 1)
3523d8536b4Sopenharmony_ci#define OS_REG_LR_OFFSET       (CONTEXT_SIZE - 8)
3533d8536b4Sopenharmony_ci
3543d8536b4Sopenharmony_ciUINT32 IsSpAligned(UINT32 value)
3553d8536b4Sopenharmony_ci{
3563d8536b4Sopenharmony_ci    return (value & (UINT32)(ALIGN_MASK)) == 0;
3573d8536b4Sopenharmony_ci}
3583d8536b4Sopenharmony_ci
3593d8536b4Sopenharmony_ciSTATIC INLINE UINTPTR HalGetLr(VOID)
3603d8536b4Sopenharmony_ci{
3613d8536b4Sopenharmony_ci    UINTPTR regLr;
3623d8536b4Sopenharmony_ci
3633d8536b4Sopenharmony_ci    __asm__ __volatile__("mov %0, a0" : "=r"(regLr));
3643d8536b4Sopenharmony_ci
3653d8536b4Sopenharmony_ci    return regLr;
3663d8536b4Sopenharmony_ci}
3673d8536b4Sopenharmony_ci
3683d8536b4Sopenharmony_ci/* This function is used to check sp address. */
3693d8536b4Sopenharmony_ciBOOL IsValidSP(UINTPTR regSP, UINTPTR start, UINTPTR end)
3703d8536b4Sopenharmony_ci{
3713d8536b4Sopenharmony_ci    return (regSP >= start) && (regSP <= end) && IsSpAligned(regSP);
3723d8536b4Sopenharmony_ci}
3733d8536b4Sopenharmony_ci
3743d8536b4Sopenharmony_ci/* This function is used to check return address. */
3753d8536b4Sopenharmony_ciBOOL IsValidRa(UINTPTR regRA)
3763d8536b4Sopenharmony_ci{
3773d8536b4Sopenharmony_ci    regRA &= ~VIR_TEXT_ADDR_MASK;
3783d8536b4Sopenharmony_ci    regRA |= TEXT_ADDR_MASK;
3793d8536b4Sopenharmony_ci
3803d8536b4Sopenharmony_ci    return OsStackDataIsCodeAddr(regRA);
3813d8536b4Sopenharmony_ci}
3823d8536b4Sopenharmony_ci
3833d8536b4Sopenharmony_ciBOOL FindSuitableStack(UINTPTR regSP, UINTPTR *start, UINTPTR *end)
3843d8536b4Sopenharmony_ci{
3853d8536b4Sopenharmony_ci    UINT32 stackStart;
3863d8536b4Sopenharmony_ci    UINT32 stackEnd;
3873d8536b4Sopenharmony_ci    BOOL found = FALSE;
3883d8536b4Sopenharmony_ci
3893d8536b4Sopenharmony_ci    if (LOS_TaskIsRunning()) {
3903d8536b4Sopenharmony_ci        UINT32 taskID = LOS_CurTaskIDGet();
3913d8536b4Sopenharmony_ci        LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
3923d8536b4Sopenharmony_ci        stackStart = taskCB->topOfStack;
3933d8536b4Sopenharmony_ci        stackEnd = taskCB->topOfStack + taskCB->stackSize;
3943d8536b4Sopenharmony_ci        if (IsValidSP(regSP, stackStart, stackEnd)) {
3953d8536b4Sopenharmony_ci            found = TRUE;
3963d8536b4Sopenharmony_ci            goto FOUND;
3973d8536b4Sopenharmony_ci        }
3983d8536b4Sopenharmony_ci    }
3993d8536b4Sopenharmony_ci
4003d8536b4Sopenharmony_ci    if (IsValidSP(regSP, CSTACK_START_ADDR, CSTACK_END_ADDR)) {
4013d8536b4Sopenharmony_ci        stackStart = CSTACK_START_ADDR;
4023d8536b4Sopenharmony_ci        stackEnd = CSTACK_END_ADDR;
4033d8536b4Sopenharmony_ci        found = TRUE;
4043d8536b4Sopenharmony_ci        goto FOUND;
4053d8536b4Sopenharmony_ci    }
4063d8536b4Sopenharmony_ci
4073d8536b4Sopenharmony_ciFOUND:
4083d8536b4Sopenharmony_ci    if (found == TRUE) {
4093d8536b4Sopenharmony_ci        *start = stackStart;
4103d8536b4Sopenharmony_ci        *end = stackEnd;
4113d8536b4Sopenharmony_ci    }
4123d8536b4Sopenharmony_ci
4133d8536b4Sopenharmony_ci    return found;
4143d8536b4Sopenharmony_ci}
4153d8536b4Sopenharmony_ci
4163d8536b4Sopenharmony_ciUINT32 HalBackTraceGet(UINTPTR sp, UINT32 retAddr, UINTPTR *callChain, UINT32 maxDepth, UINT32 jumpCount)
4173d8536b4Sopenharmony_ci{
4183d8536b4Sopenharmony_ci    UINTPTR tmpSp;
4193d8536b4Sopenharmony_ci    UINT32 tmpRa;
4203d8536b4Sopenharmony_ci    UINTPTR backRa = retAddr;
4213d8536b4Sopenharmony_ci    UINTPTR backSp = sp;
4223d8536b4Sopenharmony_ci    UINTPTR stackStart;
4233d8536b4Sopenharmony_ci    UINT32 stackEnd;
4243d8536b4Sopenharmony_ci    UINT32 count = 0;
4253d8536b4Sopenharmony_ci    UINT32 index = 0;
4263d8536b4Sopenharmony_ci
4273d8536b4Sopenharmony_ci    if (FindSuitableStack(sp, &stackStart, &stackEnd) == FALSE) {
4283d8536b4Sopenharmony_ci        PRINTK("sp:0x%x error, backtrace failed!\n", sp);
4293d8536b4Sopenharmony_ci        return 0;
4303d8536b4Sopenharmony_ci    }
4313d8536b4Sopenharmony_ci
4323d8536b4Sopenharmony_ci    while (IsValidSP(backSp, stackStart, stackEnd)) {
4333d8536b4Sopenharmony_ci        if (callChain == NULL) {
4343d8536b4Sopenharmony_ci            PRINTK("trace%u  ra:0x%x  sp:0x%x\n", count, (backRa << WINDOW_INCREMENT_SHIFT) >>
4353d8536b4Sopenharmony_ci                    WINDOW_INCREMENT_SHIFT, backSp);
4363d8536b4Sopenharmony_ci        } else {
4373d8536b4Sopenharmony_ci            if (index++ < jumpCount) {
4383d8536b4Sopenharmony_ci                continue;
4393d8536b4Sopenharmony_ci            }
4403d8536b4Sopenharmony_ci            backRa &= ~VIR_TEXT_ADDR_MASK;
4413d8536b4Sopenharmony_ci            backRa |= TEXT_ADDR_MASK;
4423d8536b4Sopenharmony_ci            callChain[count++] = backRa;
4433d8536b4Sopenharmony_ci        }
4443d8536b4Sopenharmony_ci
4453d8536b4Sopenharmony_ci        tmpRa = backRa;
4463d8536b4Sopenharmony_ci        tmpSp = backSp;
4473d8536b4Sopenharmony_ci        backRa = *((UINT32 *)(UINTPTR)(tmpSp - RA_OFFSET));
4483d8536b4Sopenharmony_ci        backSp = *((UINT32 *)(UINTPTR)(tmpSp - SP_OFFSET));
4493d8536b4Sopenharmony_ci
4503d8536b4Sopenharmony_ci        if ((tmpRa == backRa) || (backSp == tmpSp) || (count == maxDepth) || !IsValidRa(backRa)) {
4513d8536b4Sopenharmony_ci            break;
4523d8536b4Sopenharmony_ci        }
4533d8536b4Sopenharmony_ci    }
4543d8536b4Sopenharmony_ci
4553d8536b4Sopenharmony_ci    return count;
4563d8536b4Sopenharmony_ci}
4573d8536b4Sopenharmony_ci
4583d8536b4Sopenharmony_ciVOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
4593d8536b4Sopenharmony_ci{
4603d8536b4Sopenharmony_ci    UINTPTR reglr;
4613d8536b4Sopenharmony_ci    if (LR == NULL) {
4623d8536b4Sopenharmony_ci        return;
4633d8536b4Sopenharmony_ci    }
4643d8536b4Sopenharmony_ci
4653d8536b4Sopenharmony_ci    if (SP == 0) {
4663d8536b4Sopenharmony_ci        __asm__ __volatile__("mov %0, sp" : "=a"(SP) : :);
4673d8536b4Sopenharmony_ci        __asm__ __volatile__("mov %0, a0" : "=a"(reglr) : :);
4683d8536b4Sopenharmony_ci    } else {
4693d8536b4Sopenharmony_ci        reglr = *(UINT32 *)(SP - OS_REG_LR_OFFSET);
4703d8536b4Sopenharmony_ci    }
4713d8536b4Sopenharmony_ci    HakSpillWindow();
4723d8536b4Sopenharmony_ci    HalBackTraceGet(SP, reglr, LR, LRSize, jumpCount);
4733d8536b4Sopenharmony_ci}
4743d8536b4Sopenharmony_ci#elif (LOSCFG_BACKTRACE_TYPE == 5)
4753d8536b4Sopenharmony_ci#define OS_BACKTRACE_START     0
4763d8536b4Sopenharmony_ci
4773d8536b4Sopenharmony_ciUINT32 IsAligned(UINT32 val, UINT32 align)
4783d8536b4Sopenharmony_ci{
4793d8536b4Sopenharmony_ci    return ((val & (align - 1)) == 0);
4803d8536b4Sopenharmony_ci}
4813d8536b4Sopenharmony_ci
4823d8536b4Sopenharmony_ciSTATIC INLINE UINTPTR OsSpGet(VOID)
4833d8536b4Sopenharmony_ci{
4843d8536b4Sopenharmony_ci    UINTPTR regSp;
4853d8536b4Sopenharmony_ci
4863d8536b4Sopenharmony_ci    __asm__ __volatile__("mov %0, sp" : "=r"(regSp));
4873d8536b4Sopenharmony_ci
4883d8536b4Sopenharmony_ci    return regSp;
4893d8536b4Sopenharmony_ci}
4903d8536b4Sopenharmony_ci
4913d8536b4Sopenharmony_ci/* This function is used to check sp. */
4923d8536b4Sopenharmony_ciBOOL IsValidSP(UINTPTR regSP, UINTPTR start, UINTPTR end)
4933d8536b4Sopenharmony_ci{
4943d8536b4Sopenharmony_ci    return (regSP >= start) && (regSP <= end);
4953d8536b4Sopenharmony_ci}
4963d8536b4Sopenharmony_ci
4973d8536b4Sopenharmony_ciBOOL FindSuitableStack(UINTPTR regSP, UINTPTR *start, UINTPTR *end)
4983d8536b4Sopenharmony_ci{
4993d8536b4Sopenharmony_ci    UINT32 stackStart;
5003d8536b4Sopenharmony_ci    UINT32 stackEnd;
5013d8536b4Sopenharmony_ci    BOOL found = FALSE;
5023d8536b4Sopenharmony_ci
5033d8536b4Sopenharmony_ci    if (LOS_TaskIsRunning()) {
5043d8536b4Sopenharmony_ci        UINT32 taskID = LOS_CurTaskIDGet();
5053d8536b4Sopenharmony_ci        LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
5063d8536b4Sopenharmony_ci        stackStart = taskCB->topOfStack;
5073d8536b4Sopenharmony_ci        stackEnd = taskCB->topOfStack + taskCB->stackSize;
5083d8536b4Sopenharmony_ci        if (IsValidSP(regSP, stackStart, stackEnd)) {
5093d8536b4Sopenharmony_ci            found = TRUE;
5103d8536b4Sopenharmony_ci            goto FOUND;
5113d8536b4Sopenharmony_ci        }
5123d8536b4Sopenharmony_ci    }
5133d8536b4Sopenharmony_ci
5143d8536b4Sopenharmony_ci    if (IsValidSP(regSP, CSTACK_START_ADDR, CSTACK_END_ADDR)) {
5153d8536b4Sopenharmony_ci        stackStart = CSTACK_START_ADDR;
5163d8536b4Sopenharmony_ci        stackEnd = CSTACK_END_ADDR;
5173d8536b4Sopenharmony_ci        found = TRUE;
5183d8536b4Sopenharmony_ci        goto FOUND;
5193d8536b4Sopenharmony_ci    }
5203d8536b4Sopenharmony_ci
5213d8536b4Sopenharmony_ciFOUND:
5223d8536b4Sopenharmony_ci    if (found == TRUE) {
5233d8536b4Sopenharmony_ci        *start = stackStart;
5243d8536b4Sopenharmony_ci        *end = stackEnd;
5253d8536b4Sopenharmony_ci    }
5263d8536b4Sopenharmony_ci
5273d8536b4Sopenharmony_ci    return found;
5283d8536b4Sopenharmony_ci}
5293d8536b4Sopenharmony_ci
5303d8536b4Sopenharmony_ciVOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
5313d8536b4Sopenharmony_ci{
5323d8536b4Sopenharmony_ci    UINTPTR stackPointer;
5333d8536b4Sopenharmony_ci    UINTPTR topOfStack;
5343d8536b4Sopenharmony_ci    UINTPTR tmpStack = 0;
5353d8536b4Sopenharmony_ci    UINTPTR stackBottom;
5363d8536b4Sopenharmony_ci    UINTPTR checkBL;
5373d8536b4Sopenharmony_ci    UINT32 count = 0;
5383d8536b4Sopenharmony_ci    UINT32 index = 0;
5393d8536b4Sopenharmony_ci
5403d8536b4Sopenharmony_ci    if (LR == NULL) {
5413d8536b4Sopenharmony_ci        return;
5423d8536b4Sopenharmony_ci    }
5433d8536b4Sopenharmony_ci
5443d8536b4Sopenharmony_ci    if (SP == 0) {
5453d8536b4Sopenharmony_ci        SP = OsSpGet();
5463d8536b4Sopenharmony_ci    }
5473d8536b4Sopenharmony_ci
5483d8536b4Sopenharmony_ci    stackPointer = SP;
5493d8536b4Sopenharmony_ci
5503d8536b4Sopenharmony_ci    if (FindSuitableStack(stackPointer, &topOfStack, &stackBottom) == FALSE) {
5513d8536b4Sopenharmony_ci        return;
5523d8536b4Sopenharmony_ci    }
5533d8536b4Sopenharmony_ci
5543d8536b4Sopenharmony_ci    while ((stackPointer < stackBottom) && (count < LRSize)) {
5553d8536b4Sopenharmony_ci        if (IsValidSP(*(UINT32 *)stackPointer, topOfStack, stackBottom)
5563d8536b4Sopenharmony_ci            && OsStackDataIsCodeAddr(*(UINT32 *)(stackPointer + STACK_OFFSET))
5573d8536b4Sopenharmony_ci            && IsAligned(*(UINT32 *)stackPointer, ALGIN_CODE)) {
5583d8536b4Sopenharmony_ci            if (tmpStack == *(UINT32 *)stackPointer) {
5593d8536b4Sopenharmony_ci                break;
5603d8536b4Sopenharmony_ci            }
5613d8536b4Sopenharmony_ci            tmpStack = *(UINT32 *)stackPointer;
5623d8536b4Sopenharmony_ci            checkBL = *(UINT32 *)(stackPointer + STACK_OFFSET);
5633d8536b4Sopenharmony_ci            if (count++ < jumpCount) {
5643d8536b4Sopenharmony_ci                continue;
5653d8536b4Sopenharmony_ci            }
5663d8536b4Sopenharmony_ci            stackPointer = tmpStack;
5673d8536b4Sopenharmony_ci            LR[index++] =  checkBL;
5683d8536b4Sopenharmony_ci            continue;
5693d8536b4Sopenharmony_ci        }
5703d8536b4Sopenharmony_ci        stackPointer += STACK_OFFSET;
5713d8536b4Sopenharmony_ci    }
5723d8536b4Sopenharmony_ci
5733d8536b4Sopenharmony_ci    if (index < LRSize) {
5743d8536b4Sopenharmony_ci        LR[index] = 0;
5753d8536b4Sopenharmony_ci    }
5763d8536b4Sopenharmony_ci}
5773d8536b4Sopenharmony_ci#elif (LOSCFG_BACKTRACE_TYPE == 6)
5783d8536b4Sopenharmony_ci#define OS_BACKTRACE_START               1
5793d8536b4Sopenharmony_ci#define STACK_OFFSET                     4
5803d8536b4Sopenharmony_ci#define THUMB_OFFSET                     2
5813d8536b4Sopenharmony_ci#define THUMB_BIT                        16
5823d8536b4Sopenharmony_ci#define ARM_ALIGN_CODE                   4
5833d8536b4Sopenharmony_ci#define THUMB_ALIGN_CODE                 2
5843d8536b4Sopenharmony_ci#define BL_CMD_OFFSET                    4
5853d8536b4Sopenharmony_ci#define ARM_BL_MASK                      0xEB000000
5863d8536b4Sopenharmony_ci#define THUMB_BL_MASK                    0xF000F000
5873d8536b4Sopenharmony_ci#define CLEAR_LOW_BIT_MASK               0xFFFFFFFE
5883d8536b4Sopenharmony_ci
5893d8536b4Sopenharmony_ciSTATIC INLINE BOOL IsAligned(UINT32 val, UINT32 align)
5903d8536b4Sopenharmony_ci{
5913d8536b4Sopenharmony_ci    return ((val & (align - 1)) == 0);
5923d8536b4Sopenharmony_ci}
5933d8536b4Sopenharmony_ci
5943d8536b4Sopenharmony_ciSTATIC INLINE UINTPTR OsSpGet(VOID)
5953d8536b4Sopenharmony_ci{
5963d8536b4Sopenharmony_ci    UINTPTR SP;
5973d8536b4Sopenharmony_ci    __asm volatile("mov %0, sp" : "=r"(SP));
5983d8536b4Sopenharmony_ci    return SP;
5993d8536b4Sopenharmony_ci}
6003d8536b4Sopenharmony_ci
6013d8536b4Sopenharmony_ciSTATIC INLINE BOOL IsArmValidLr(UINTPTR lr)
6023d8536b4Sopenharmony_ci{
6033d8536b4Sopenharmony_ci    return ((*(UINT32 *)(lr - BL_CMD_OFFSET) & ARM_BL_MASK) == ARM_BL_MASK);
6043d8536b4Sopenharmony_ci}
6053d8536b4Sopenharmony_ci
6063d8536b4Sopenharmony_ciSTATIC INLINE BOOL IsThumbValidLr(UINTPTR lr)
6073d8536b4Sopenharmony_ci{
6083d8536b4Sopenharmony_ci    lr = (*(UINT16 *)(lr - BL_CMD_OFFSET) << THUMB_BIT) + *(UINT16 *)(lr - THUMB_OFFSET);
6093d8536b4Sopenharmony_ci    return ((lr & THUMB_BL_MASK) == THUMB_BL_MASK);
6103d8536b4Sopenharmony_ci}
6113d8536b4Sopenharmony_ci
6123d8536b4Sopenharmony_ciVOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
6133d8536b4Sopenharmony_ci{
6143d8536b4Sopenharmony_ci    UINT32 count = 0;
6153d8536b4Sopenharmony_ci    UINT32 index = 0;
6163d8536b4Sopenharmony_ci    LosTaskCB *taskCB = NULL;
6173d8536b4Sopenharmony_ci    UINT32 taskID;
6183d8536b4Sopenharmony_ci    UINT32 stackStart, stackEnd;
6193d8536b4Sopenharmony_ci    UINTPTR framePtr, tmpFramePtr, linkReg;
6203d8536b4Sopenharmony_ci
6213d8536b4Sopenharmony_ci    if (LR == NULL) {
6223d8536b4Sopenharmony_ci        return;
6233d8536b4Sopenharmony_ci    }
6243d8536b4Sopenharmony_ci
6253d8536b4Sopenharmony_ci    if (SP == 0) {
6263d8536b4Sopenharmony_ci        SP = OsSpGet();
6273d8536b4Sopenharmony_ci    }
6283d8536b4Sopenharmony_ci
6293d8536b4Sopenharmony_ci    if (LOS_TaskIsRunning()) {
6303d8536b4Sopenharmony_ci        taskID = LOS_CurTaskIDGet();
6313d8536b4Sopenharmony_ci        taskCB = OS_TCB_FROM_TID(taskID);
6323d8536b4Sopenharmony_ci        stackStart = taskCB->topOfStack;
6333d8536b4Sopenharmony_ci        stackEnd = stackStart + taskCB->stackSize;
6343d8536b4Sopenharmony_ci    } else {
6353d8536b4Sopenharmony_ci        stackStart = CSTACK_START_ADDR;
6363d8536b4Sopenharmony_ci        stackEnd = CSTACK_END_ADDR;
6373d8536b4Sopenharmony_ci    }
6383d8536b4Sopenharmony_ci
6393d8536b4Sopenharmony_ci    while ((SP > stackStart) && (SP < stackEnd)) {
6403d8536b4Sopenharmony_ci        linkReg = *(UINTPTR *)SP;
6413d8536b4Sopenharmony_ci        if (!OsStackDataIsCodeAddr(linkReg)) {
6423d8536b4Sopenharmony_ci            SP += STACK_OFFSET;
6433d8536b4Sopenharmony_ci            continue;
6443d8536b4Sopenharmony_ci        }
6453d8536b4Sopenharmony_ci        if (((!IsAligned(linkReg, ARM_ALIGN_CODE)) || !IsArmValidLr(linkReg)) &&
6463d8536b4Sopenharmony_ci            ((!IsAligned(linkReg - 1, THUMB_ALIGN_CODE)) || !IsThumbValidLr(linkReg - 1))) {
6473d8536b4Sopenharmony_ci            SP += STACK_OFFSET;
6483d8536b4Sopenharmony_ci            continue;
6493d8536b4Sopenharmony_ci        }
6503d8536b4Sopenharmony_ci        if (index >= jumpCount) {
6513d8536b4Sopenharmony_ci            LR[count++] = linkReg & CLEAR_LOW_BIT_MASK;
6523d8536b4Sopenharmony_ci            if (count == LRSize) {
6533d8536b4Sopenharmony_ci                break;
6543d8536b4Sopenharmony_ci            }
6553d8536b4Sopenharmony_ci        }
6563d8536b4Sopenharmony_ci        ++index;
6573d8536b4Sopenharmony_ci        SP += STACK_OFFSET;
6583d8536b4Sopenharmony_ci    }
6593d8536b4Sopenharmony_ci
6603d8536b4Sopenharmony_ci    /* if linkReg is not enough,clean up the last of the effective LR as the end. */
6613d8536b4Sopenharmony_ci    if (count < LRSize) {
6623d8536b4Sopenharmony_ci        LR[count] = 0;
6633d8536b4Sopenharmony_ci    }
6643d8536b4Sopenharmony_ci}
6653d8536b4Sopenharmony_ci#else
6663d8536b4Sopenharmony_ci#error Unknown backtrace type.
6673d8536b4Sopenharmony_ci#endif
6683d8536b4Sopenharmony_ci
6693d8536b4Sopenharmony_ci#if (LOSCFG_BACKTRACE_TYPE == 1) || (LOSCFG_BACKTRACE_TYPE == 3)
6703d8536b4Sopenharmony_ciVOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
6713d8536b4Sopenharmony_ci{
6723d8536b4Sopenharmony_ci    if (LR == NULL) {
6733d8536b4Sopenharmony_ci        return;
6743d8536b4Sopenharmony_ci    }
6753d8536b4Sopenharmony_ci
6763d8536b4Sopenharmony_ci    UINTPTR stackStart;
6773d8536b4Sopenharmony_ci    UINTPTR stackEnd;
6783d8536b4Sopenharmony_ci    UINT32 count = 0;
6793d8536b4Sopenharmony_ci    UINT32 index = 0;
6803d8536b4Sopenharmony_ci    UINTPTR sp;
6813d8536b4Sopenharmony_ci    UINTPTR pc;
6823d8536b4Sopenharmony_ci    UINT32 ret;
6833d8536b4Sopenharmony_ci
6843d8536b4Sopenharmony_ci    ret = OsStackAddrGet(&stackStart, &stackEnd, SP);
6853d8536b4Sopenharmony_ci    if (ret != LOS_OK) {
6863d8536b4Sopenharmony_ci        return;
6873d8536b4Sopenharmony_ci    }
6883d8536b4Sopenharmony_ci
6893d8536b4Sopenharmony_ci    /* Traverse the stack space and find the LR address. */
6903d8536b4Sopenharmony_ci    for (sp = stackStart; sp < stackEnd; sp += sizeof(UINTPTR)) {
6913d8536b4Sopenharmony_ci        pc = OsAddrIsValid(sp);
6923d8536b4Sopenharmony_ci        if ((pc != 0) && (count < LRSize)) {
6933d8536b4Sopenharmony_ci            if (index++ < jumpCount) {
6943d8536b4Sopenharmony_ci                continue;
6953d8536b4Sopenharmony_ci            }
6963d8536b4Sopenharmony_ci            LR[count] = pc;
6973d8536b4Sopenharmony_ci            count++;
6983d8536b4Sopenharmony_ci            if (count == LRSize) {
6993d8536b4Sopenharmony_ci                break;
7003d8536b4Sopenharmony_ci            }
7013d8536b4Sopenharmony_ci        }
7023d8536b4Sopenharmony_ci    }
7033d8536b4Sopenharmony_ci
7043d8536b4Sopenharmony_ci    if (count < LRSize) {
7053d8536b4Sopenharmony_ci        LR[count] = 0;
7063d8536b4Sopenharmony_ci    }
7073d8536b4Sopenharmony_ci}
7083d8536b4Sopenharmony_ci#endif
7093d8536b4Sopenharmony_ci
7103d8536b4Sopenharmony_ciVOID LOS_BackTrace(VOID)
7113d8536b4Sopenharmony_ci{
7123d8536b4Sopenharmony_ci    UINTPTR LR[BACKTRACE_MAX_DEPTH] = {0};
7133d8536b4Sopenharmony_ci    UINT32 index;
7143d8536b4Sopenharmony_ci
7153d8536b4Sopenharmony_ci    LOS_RecordLR(LR, BACKTRACE_MAX_DEPTH, OS_BACKTRACE_START, 0);
7163d8536b4Sopenharmony_ci
7173d8536b4Sopenharmony_ci    if (LOS_TaskIsRunning()) {
7183d8536b4Sopenharmony_ci        PRINTK("taskName = %s\n", g_losTask.runTask->taskName);
7193d8536b4Sopenharmony_ci        PRINTK("taskID   = %u\n", g_losTask.runTask->taskID);
7203d8536b4Sopenharmony_ci    }
7213d8536b4Sopenharmony_ci
7223d8536b4Sopenharmony_ci    PRINTK("----- traceback start -----\r\n");
7233d8536b4Sopenharmony_ci    for (index = 0; index < BACKTRACE_MAX_DEPTH; index++) {
7243d8536b4Sopenharmony_ci        if (LR[index] == 0) {
7253d8536b4Sopenharmony_ci            break;
7263d8536b4Sopenharmony_ci        }
7273d8536b4Sopenharmony_ci        PRINTK("traceback %d -- lr = 0x%x\r\n", index, LR[index]);
7283d8536b4Sopenharmony_ci    }
7293d8536b4Sopenharmony_ci    PRINTK("----- traceback end -----\r\n");
7303d8536b4Sopenharmony_ci}
7313d8536b4Sopenharmony_ci
7323d8536b4Sopenharmony_ciVOID OsBackTraceInit(VOID)
7333d8536b4Sopenharmony_ci{
7343d8536b4Sopenharmony_ci    OsBackTraceHookSet(LOS_RecordLR);
7353d8536b4Sopenharmony_ci}
7363d8536b4Sopenharmony_ci#endif
7373d8536b4Sopenharmony_ci
738