1# Exception Debugging 2 3 4## Basic Concepts 5 6The OpenHarmony LiteOS-M provides exception handling and debugging measures to help locate and analyze problems. Exception handling involves a series of actions taken by the OS to respond to exceptions occurred during the OS running, for example, printing the exception type, system status, call stack information of the current function, CPU information, and call stack information of tasks. 7 8 9## Working Principles 10 11A stack frame contains information such as function parameters, variables, and return value in a function call process. When a function is called, a stack frame of the subfunction is created, and the input parameters, local variables, and registers of the function are stored into the stack. Stack frames grow towards lower addresses. The ARM32 CPU architecture is used as an example. Each stack frame stores the historical values of the program counter (PC), link register (LR), stack pointer (SP), and frame pointer (FP) registers. The LR points to the return address of a function, and the FP points to the start address of the stack frame of the function's parent function. The FP helps locate the parent function's stack frame, which further helps locate the parent function's FP. The parent function's FP helps locate the grandparent function's stack frame and FP... In this way, the call stack of the program can be traced to obtain the relationship between the functions called. 12 13When an exception occurs in the system, the system prints the register information in the stack frame of the abnormal function as well as the LRs and FPs in the stack frames of its parent function and grandfather function. The relationships between the functions help you locate the cause of the exception. 14 15The following figure illustrates the stack analysis mechanism for your reference. The actual stack information varies depending on the CPU architecture. 16 17**Figure 1** Stack analysis mechanism 18 19![](figures/stack-analysis-mechanism.png "stack-analysis-mechanism") 20 21In the figure, the registers in different colors indicate different functions. The registers save related data when functions are called. The FP register helps track the stack to the parent function of the abnormal function and further presents the relationships between the functions called. 22 23 24## Available APIs 25 26The following table describes APIs available for the OpenHarmony LiteOS-M stack trace module. For more details about the APIs, see the API reference. 27 28 **Table 1** APIs of the stack trace module 29 30| Category| API| 31| -------- | -------- | 32| Stack tracing| **LOS_BackTrace**: prints the call stack relationship at the calling point.<br>**LOS_RecordLR**: obtains the call stack relationship at the calling point when print is unavailable.| 33 34 35## Development Guidelines 36 37 38### How to Develop 39 40The typical process for enabling exception debugging is as follows: 41 421. Configure the macros related to exception handling 43 in the **target_config.h** file. 44 | Configuration Item| Description| Value| 45 | -------- | -------- | -------- | 46 | LOSCFG_BACKTRACE_DEPTH | Depth of the function call stack. The default value is **15**.| 15 | 47 | LOSCFG_BACKTRACE_TYPE | Type of the stack tracing.<br>**0**: The stack tracing is disabled.<br>**1**: supports call stack analysis of the Cortex-M series hardware.<br>**2**: supports call stack analysis of the RISC-V series hardware.| Set this parameter to **1** or **2** based on the toolchain type.| 48 491. Use the error code in the example to build and run a project, and check the error information displayed on the serial port terminal. The sample code simulates error code. During actual product development, use the exception debugging mechanism to locate exceptions. 50 The following example demonstrates the exception output through a task. The task entry function simulates calling of multiple functions and finally calls a function that simulates an exception. The sample code is as follows: 51 52 The sample code can be compiled and verified in **./kernel/liteos_m/testsuites/src/osTest.c**. The **ExampleExcEntry** function is called in **TestTaskEntry**. 53 54 ``` 55 #include <stdio.h> 56 #include "los_config.h" 57 #include "los_interrupt.h" 58 #include "los_task.h" 59 60 UINT32 g_taskExcId; 61 #define TSK_PRIOR 4 62 63 /* Simulate an exception. */ 64 UINT32 GetResultException0(UINT16 dividend){ 65 UINT32 result = *(UINT32 *)(0xffffffff); 66 printf("Enter GetResultException0. %u\r\n", result); 67 return result; 68 } 69 70 UINT32 GetResultException1(UINT16 dividend){ 71 printf("Enter GetResultException1.\r\n"); 72 return GetResultException0(dividend); 73 } 74 75 UINT32 GetResultException2(UINT16 dividend){ 76 printf("Enter GetResultException2.\r\n"); 77 return GetResultException1(dividend); 78 } 79 80 UINT32 ExampleExc(VOID) 81 { 82 UINT32 ret; 83 84 printf("Enter Example_Exc Handler.\r\n"); 85 86 /* Simulate the triggering of the exception. */ 87 ret = GetResultException2(TSK_PRIOR); 88 printf("Divided result =%u.\r\n", ret); 89 90 printf("Exit Example_Exc Handler.\r\n"); 91 return ret; 92 } 93 94 95 /* Create a task with an exception in the task entry function. */ 96 UINT32 ExampleExcEntry(VOID) 97 { 98 UINT32 ret; 99 TSK_INIT_PARAM_S initParam = { 0 }; 100 101 /* Lock task scheduling to prevent newly created tasks from being scheduled prior to this task due to higher priority. */ 102 LOS_TaskLock(); 103 104 printf("LOS_TaskLock() Success!\r\n"); 105 106 initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleExc; 107 initParam.usTaskPrio = TSK_PRIOR; 108 initParam.pcName = "Example_Exc"; 109 initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; 110 /* Create a task with a higher priority. The task will not be executed because task scheduling is locked. */ 111 ret = LOS_TaskCreate(&g_taskExcId, &initParam); 112 if (ret != LOS_OK) { 113 LOS_TaskUnlock(); 114 115 printf("Example_Exc create Failed!\r\n"); 116 return LOS_NOK; 117 } 118 119 printf("Example_Exc create Success!\r\n"); 120 121 /* Unlock task scheduling. The task with the highest priority in the Ready queue will be executed. */ 122 LOS_TaskUnlock(); 123 124 return LOS_OK; 125 } 126 ``` 127 128 The error information output by the serial port terminal is as follows: 129 130 ``` 131 LOS_TaskLock() Success! 132 Example_Exc create Success! 133 Enter Example_Exc Handler. 134 Enter GetResultException2. 135 Enter GetResultException1. 136 *************Exception Information************** 137 Type = 4 138 ThrdPid = 5 139 Phase = exc in task 140 FaultAddr = 0xfffffffc 141 Current task info: 142 Task name = Example_Exc 143 Task ID = 5 144 Task SP = 0x210549bc 145 Task ST = 0x21053a00 146 Task SS = 0x1000 147 Exception reg dump: 148 PC = 0x2101c61a 149 LR = 0x2101c64d 150 SP = 0x210549a8 151 R0 = 0x4 152 R1 = 0xa 153 R2 = 0x0 154 R3 = 0xffffffff 155 R4 = 0x2103fb20 156 R5 = 0x5050505 157 R6 = 0x6060606 158 R7 = 0x210549a8 159 R8 = 0x8080808 160 R9 = 0x9090909 161 R10 = 0x10101010 162 R11 = 0x11111111 163 R12 = 0x0 164 PriMask = 0x0 165 xPSR = 0x41000000 166 ----- backtrace start ----- 167 backtrace 0 -- lr = 0x2101c64c 168 backtrace 1 -- lr = 0x2101c674 169 backtrace 2 -- lr = 0x2101c696 170 backtrace 3 -- lr = 0x2101b1ec 171 ----- backtrace end ----- 172 173 TID Priority Status StackSize WaterLine StackPoint TopOfStack EventMask SemID CPUUSE CPUUSE10s CPUUSE1s TaskEntry name 174 --- -------- -------- --------- --------- ---------- ---------- --------- ------ ------- --------- -------- ---------- ---- 175 0 0 Pend 0x1000 0xdc 0x2104730c 0x210463e8 0 0xffff 0.0 0.0 0.0 0x2101a199 Swt_Task 176 1 31 Ready 0x500 0x44 0x210478e4 0x21047428 0 0xffff 0.0 0.0 0.0 0x2101a9c9 IdleCore000 177 2 5 PendTime 0x6000 0xd4 0x2104e8f4 0x210489c8 0 0xffff 5.7 5.7 0.0 0x21016149 tcpip_thread 178 3 3 Pend 0x1000 0x488 0x2104f90c 0x2104e9e8 0x1 0xffff 8.6 8.6 0.0 0x21016db5 ShellTaskEntry 179 4 25 Ready 0x4000 0x460 0x21053964 0x2104f9f0 0 0xffff 9.0 8.9 0.0 0x2101c765 IT_TST_INI 180 5 4 Running 0x1000 0x458 0x210549bc 0x21053a00 0 0xffff 76.5 76.6 0.0 0x2101c685 Example_Exc 181 182 OS exception NVIC dump: 183 interrupt enable register, base address: 0xe000e100, size: 0x20 184 0x2001 0x0 0x0 0x0 0x0 0x0 0x0 0x0 185 interrupt pending register, base address: 0xe000e200, size: 0x20 186 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 187 interrupt active register, base address: 0xe000e300, size: 0x20 188 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 189 interrupt priority register, base address: 0xe000e400, size: 0xf0 190 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 191 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 192 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 193 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 194 interrupt exception register, base address: 0xe000ed18, size: 0xc 195 0x0 0x0 0xf0f00000 196 interrupt shcsr register, base address: 0xe000ed24, size: 0x4 197 0x70002 198 interrupt control register, base address: 0xe000ed04, size: 0x4 199 0x1000e805 200 201 memory pools check: 202 system heap memcheck over, all passed! 203 memory pool check end! 204 205 The preceding data may vary depending on the running environment. 206 ``` 207 208 209### How to Locate Exceptions 210 211The procedure for locating the exception is as follows: 212 2131. Ensure that the compiler optimization is disabled. Otherwise, the following problems may be optimized during the compilation process. 214 2152. Open the image disassembly file (.asm) generated. If the file is not generated, use the objdump tool to generate it. The command is as follows: 216 217 ``` 218 arm-none-eabi-objdump -S -l XXX.elf 219 ``` 220 2213. Search for the PC (pointing to the instruction being executed) in the .asm file to locate the abnormal function. 222 223 The PC address directs to the instruction being executed when the exception occurs. In the .asm file corresponding to the currently executed binary file, search for the PC value **0x2101c61a** and locate the instruction being executed by the CPU. Disassemble the code as follows: 224 225 ``` 226 2101c60c <GetResultException0>: 227 2101c60c: b580 push {r7, lr} 228 2101c60e: b084 sub sp, #16 229 2101c610: af00 add r7, sp, #0 230 2101c612: 4603 mov r3, r0 231 2101c614: 80fb strh r3, [r7, #6] 232 2101c616: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff 233 2101c61a: 681b ldr r3, [r3, #0] 234 2101c61c: 60fb str r3, [r7, #12] 235 2101c61e: 68f9 ldr r1, [r7, #12] 236 2101c620: 4803 ldr r0, [pc, #12] ; (2101c630 <GetResultException0+0x24>) 237 2101c622: f001 f92b bl 2101d87c <printf> 238 2101c626: 68fb ldr r3, [r7, #12] 239 2101c628: 4618 mov r0, r3 240 2101c62a: 3710 adds r7, #16 241 2101c62c: 46bd mov sp, r7 242 2101c62e: bd80 pop {r7, pc} 243 2101c630: 21025f90 .word 0x21025f90 244 ``` 245 246 As indicated by the information displayed: 247 248 - The CPU is executing **ldr r3, [r3, #0]** when an exception occurs. The value of **r3** is **0xffffffff**, which causes an invalid address. 249 - The exception occurs in the **GetResultException0** function. 250 2514. Search for the parent function of the abnormal function based on the LR value. 252 The code disassembly of the LR value **0x2101c64d** is as follows: 253 254 ``` 255 2101c634 <GetResultException1>: 256 2101c634: b580 push {r7, lr} 257 2101c636: b082 sub sp, #8 258 2101c638: af00 add r7, sp, #0 259 2101c63a: 4603 mov r3, r0 260 2101c63c: 80fb strh r3, [r7, #6] 261 2101c63e: 4806 ldr r0, [pc, #24] ; (2101c658 <GetResultException1+0x24>) 262 2101c640: f001 f91c bl 2101d87c <printf> 263 2101c644: 88fb ldrh r3, [r7, #6] 264 2101c646: 4618 mov r0, r3 265 2101c648: f7ff ffe0 bl 2101c60c <GetResultException0> 266 2101c64c: 4603 mov r3, r0 267 2101c64e: 4618 mov r0, r3 268 2101c650: 3708 adds r7, #8 269 2101c652: 46bd mov sp, r7 270 2101c654: bd80 pop {r7, pc} 271 2101c656: bf00 nop 272 2101c658: 21025fb0 .word 0x21025fb0 273 ``` 274 275 The previous line of LR **2101c648** is **bl2101c60c <GetResultException0>**, which calls the abnormal function. The parent function is **GetResultException1**. 276 2775. Parse the LR value between **backtrace start** and **backtrace end** in the exception information to obtain the call stack relationship where the exception occurs and find the cause of the exception.