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)
38 typedef struct {
39 UINT32 waterLine;
40 UINT32 taskSPTop;
41 UINT32 taskSPLimit;
42 UINTPTR taskSP;
43 } DumpInfo;
44
ShowFormat(UINTPTR *buf, DumpInfo *info)45 STATIC 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
DumpTaskInfo(UINT32 taskID, UINTPTR *buf, DumpInfo *info)67 STATIC 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
LOS_TaskStackDump(UINT32 taskID)92 VOID 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
OsShellCmdStackDump(INT32 argc, const CHAR **argv)141 UINT32 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