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