1/* 2 * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without modification, 5 * are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, this list of 8 * conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 * of conditions and the following disclaimer in the documentation and/or other materials 12 * provided with the distribution. 13 * 14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific prior written 16 * permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "los_debugtools.h" 32#include "securec.h" 33#include "los_debug.h" 34#include "los_memory.h" 35#include "los_arch.h" 36 37#if (LOSCFG_DEBUG_TOOLS == 1) 38typedef struct { 39 UINT32 waterLine; 40 UINT32 taskSPTop; 41 UINT32 taskSPLimit; 42 UINTPTR taskSP; 43} DumpInfo; 44 45STATIC VOID ShowFormat(UINTPTR *buf, DumpInfo *info) 46{ 47 INT32 i; 48 49 UINT32 len = info->waterLine / sizeof(UINTPTR); 50 UINTPTR addr = (info->taskSPLimit - info->waterLine); 51 52 for (i = 0; i < len; i++) { 53 if ((i % PRINT_PER_ROW) == 0) { 54 PRINTK("\r\n 0x%08x: ", addr); 55 } 56 if (addr == info->taskSP) { 57 PRINTK(" *%08x", buf[i]); 58 } else { 59 PRINTK(" %08x", buf[i]); 60 } 61 addr += sizeof(UINTPTR); 62 } 63 64 PRINTK("\r\n"); 65} 66 67STATIC INT32 DumpTaskInfo(UINT32 taskID, UINTPTR *buf, DumpInfo *info) 68{ 69 errno_t ret; 70 LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID); 71 72 if (taskID == LOS_CurTaskIDGet()) { 73 info->taskSP = ArchSpGet(); 74 } else { 75 info->taskSP = (UINTPTR)taskCB->stackPointer; 76 } 77 78 info->taskSPTop = taskCB->topOfStack; 79 info->taskSPLimit = taskCB->topOfStack + taskCB->stackSize; 80 if ((info->taskSP > info->taskSPLimit) || (info->taskSP < info->taskSPTop)) { 81 return LOS_NOK; 82 } 83 84 ret = memcpy_s(buf, info->waterLine, (const VOID *)(info->taskSPLimit - info->waterLine), info->waterLine); 85 if (ret != EOK) { 86 return LOS_NOK; 87 } 88 89 return LOS_OK; 90} 91 92VOID LOS_TaskStackDump(UINT32 taskID) 93{ 94 UINTPTR *buf = NULL; 95 DumpInfo info; 96 UINT32 intSave; 97 INT32 ret; 98 99 if (taskID > g_taskMaxNum) { 100 PRINT_ERR("error taskID %u\r\n", taskID); 101 return; 102 } 103 104 if (OS_INT_ACTIVE) { 105 PRINT_ERR("called during an interrupt.\r\n"); 106 return; 107 } 108 109 intSave = LOS_IntLock(); 110 info.waterLine = OsGetTaskWaterLine(taskID); 111 if (info.waterLine == OS_NULL_INT) { 112 LOS_IntRestore(intSave); 113 return; 114 } 115 116 buf = (UINTPTR *)LOS_MemAlloc(OS_SYS_MEM_ADDR, info.waterLine); 117 if (buf == NULL) { 118 LOS_IntRestore(intSave); 119 PRINT_ERR("alloc failed for dump\n"); 120 return; 121 } 122 (VOID)memset_s(buf, info.waterLine, 0, info.waterLine); 123 124 ret = DumpTaskInfo(taskID, buf, &info); 125 if (ret != LOS_OK) { 126 LOS_IntRestore(intSave); 127 (VOID)LOS_MemFree(OS_SYS_MEM_ADDR, buf); 128 PRINT_ERR("SP 0x%x may error or memcpy_s failed, stack space from 0x%x to 0x%x\r\n", \ 129 info.taskSP, info.taskSPTop, info.taskSPLimit); 130 return; 131 } 132 133 LOS_IntRestore(intSave); 134 PRINTK("Task %u, SP 0x%x, WaterLine 0x%x", taskID, info.taskSP, info.waterLine); 135 ShowFormat(buf, &info); 136 (VOID)LOS_MemFree(OS_SYS_MEM_ADDR, buf); 137 138 return; 139} 140 141UINT32 OsShellCmdStackDump(INT32 argc, const CHAR **argv) 142{ 143 UINT32 taskID; 144 145 if (argc != 1) { 146 PRINT_ERR("\nUsage: stack taskID\n"); 147 return LOS_NOK; 148 } 149 150 taskID = (UINT32)atoi(argv[0]); 151 152 LOS_TaskStackDump(taskID); 153 return LOS_OK; 154} 155#endif /* LOSCFG_STACK_DUMP == 1 */ 156