/* ---------------------------------------------------------------------------- * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. * Description: Stack Info Implementation * Author: Huawei LiteOS Team * Create: 2020-10-22 * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * 3. Neither the name of the copyright holder nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior written * permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ /* 这段文件是针对LiteOS操作系统中的Shell命令编写的, 主要实现了内核异常处理机制中与堆栈相关的功能,包括堆栈信息的获取和检查。 */ #include "securec.h" #include "los_config.h" #include "los_stackinfo_pri.h" #include "los_printf_pri.h" #ifdef LOSCFG_SHELL #include "shcmd.h" #include "shell.h" #endif //这个函数用于检查堆栈是否溢出 VOID OsExcStackCheck(VOID) { UINT32 index; UINT32 cpuid; UINTPTR *stackTop = NULL; const StackInfo *stackInfo = NULL; UINT32 stackNum; //获取堆栈信息,如果堆栈信息错误,直接返回 OsGetStackInfo(&stackInfo, &stackNum); if ((stackInfo == NULL) || (stackNum == 0)) { return; } //从头开始,遍历所有的堆栈 for (index = 0; index < stackNum; index++) { for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) { //堆栈的栈顶 stackTop = (UINTPTR *)((UINTPTR)stackInfo[index].stackTop + cpuid * stackInfo[index].stackSize); //检查栈顶信息是否被篡改,如果被篡改输出该堆栈溢出的信息 if (*stackTop != OS_STACK_MAGIC_WORD) { PRINT_ERR("cpu:%u %s overflow , magic word changed to 0x%x\n", LOSCFG_KERNEL_CORE_NUM - 1 - cpuid, stackInfo[index].stackName, *stackTop); } } } } //这个函数用于获取并打印所有的堆栈信息 VOID OsExcStackInfo(VOID) { UINT32 index; UINT32 cpuid; UINT32 size; UINTPTR *stackTop = NULL; UINTPTR *stack = NULL; const StackInfo *stackInfo = NULL; UINT32 stackNum; //获取堆栈信息,如果堆栈信息错误,直接返回 OsGetStackInfo(&stackInfo, &stackNum); if ((stackInfo == NULL) || (stackNum == 0)) { return; } //输出堆栈名、CPU ID、堆栈的地址、堆栈的总大小,堆栈已使用的大小 PrintExcInfo("\n stack name cpu id stack addr total size used size\n" " ---------- ------ --------- -------- --------\n"); //从头开始,遍历所有的堆栈 for (index = 0; index < stackNum; index++) { for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) { //获取堆栈的栈顶 stackTop = (UINTPTR *)((UINTPTR)stackInfo[index].stackTop + cpuid * stackInfo[index].stackSize); stack = (UINTPTR *)((UINTPTR)stackTop + stackInfo[index].stackSize); //调用OsStackWaterLineGet函数计算堆栈已使用的大小 (VOID)OsStackWaterLineGet(stack, stackTop, &size); //输出各类信息 PrintExcInfo("%11s %-5d %-10p 0x%-8x 0x%-4x\n", stackInfo[index].stackName, LOSCFG_KERNEL_CORE_NUM - 1 - cpuid, stackTop, stackInfo[index].stackSize, size); } } //进行堆栈溢出检查 OsExcStackCheck(); } //注册Shell命令stack,调用OsExcStackInfo函数获取并打印所有堆栈信息至控制台。 #ifdef LOSCFG_SHELL SHELLCMD_ENTRY(stack_shellcmd, CMD_TYPE_EX, "stack", 1, (CmdCallBackFunc)OsExcStackInfo); #endif