1e41f4b71Sopenharmony_ci# User-Mode Memory Debugging 2e41f4b71Sopenharmony_ci## Basic Concepts 3e41f4b71Sopenharmony_ci 4e41f4b71Sopenharmony_ciThe musl libc library of the debug version provides mechanisms, such as memory leak check, heap memory statistics, memory corruption check, and backtrace, to improve the efficiency in locating memory problems in user space. 5e41f4b71Sopenharmony_ci 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciInstrumentation is performed in the **malloc** and **free** APIs to log key node information. The memory node integrity is checked when memory is requested and released by an application. When the application ends, memory statistics are provided to help identifying memory leaks. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci## Working Principles 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci 12e41f4b71Sopenharmony_ci### Memory Leak Check 13e41f4b71Sopenharmony_ci 14e41f4b71Sopenharmony_ciThe memory debugging module maintains 128 (that is the maximum number of threads supported in the system) linked lists for each process. The index of each linked list is the thread ID. 15e41f4b71Sopenharmony_ci 16e41f4b71Sopenharmony_ciWhen memory is requested, key information is saved to the memory node control block, which is inserted to the corresponding linked list based on the thread ID. 17e41f4b71Sopenharmony_ci 18e41f4b71Sopenharmony_ciWhen memory is released, the system matches the memory node control block based on the memory address to be released and deletes the control block. 19e41f4b71Sopenharmony_ci 20e41f4b71Sopenharmony_ci**Figure 1** Heap memory node linked list 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ciWhen memory is allocated, the returned address is saved in a link register (LR). During the process running, the system adds information, such as the LR corresponding to the suspected leak, to the memory node control block. The following figure shows the heap memory node information. 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ci**Figure 2** Heap memory node information 27e41f4b71Sopenharmony_ci 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci 30e41f4b71Sopenharmony_ci**TID** indicates the thread ID; **PID** indicates the process ID; **ptr** indicates the address of the memory requested; **size** indicates the size of the requested memory; **lr[*n*]** indicates the address of the call stack, and *n* is configurable. 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ciWhen memory is released, the input parameter pointer in the **free** API is used to match the **ptr** field of the memory node. If the pointer is the same as the **ptr** field of the memory node, the memory node control block will be deleted. 33e41f4b71Sopenharmony_ci 34e41f4b71Sopenharmony_ciYou can export the memory debugging information of each process through the serial port or file, and use the addr2line tool to convert the exported information into the code lines that cause memory leaks. In this way, the memory leakage problem can be solved. 35e41f4b71Sopenharmony_ci 36e41f4b71Sopenharmony_ci**Figure 3** Process of locating the code line for a memory leak 37e41f4b71Sopenharmony_ci 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ci 41e41f4b71Sopenharmony_ci### Heap Memory Statistics 42e41f4b71Sopenharmony_ci 43e41f4b71Sopenharmony_ciYou can collect statistics on the percentage of heap memory requested by each thread to provide data support for optimizing memory usage of user programs. The **malloc** and **free** APIs are involved in user-mode heap memory statistics. As shown in the figure above, each process maintains 128 linked lists, and the index of each linked list is a thread ID. When heap memory is requested, the **ptr** and **size** information is recorded in the memory node control block, which is inserted to a linked list with the thread ID as the header. When the heap memory is released, the corresponding heap memory block is removed from the linked list based on the **ptr**. In addition, the system calculates the total heap memory used by the current thread and updates its heap memory usage and peak heap memory usage. 44e41f4b71Sopenharmony_ci 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ci### Memory Integrity Check 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci- Requested memory less than or equal to 0x1c000 bytes 49e41f4b71Sopenharmony_ci 50e41f4b71Sopenharmony_ci When the requested memory is less than or equal to 0x1c000 bytes, **malloc** uses the heap allocation algorithm to allocate memory. 51e41f4b71Sopenharmony_ci 52e41f4b71Sopenharmony_ci When a user program requests heap memory, information such as the check value is added to the heap memory node. If the check value is abnormal, it is probably that the previous heap memory block is overwritten. Currently, the scenario where the check value is damaged by a wild pointer cannot be identified. When memory is allocated or released, the memory node check value is verified. If the memory node is corrupted and the verification fails, the following information is output: TID, PID, and call stack information saved when the previous heap memory block of the corrupted node is allocated. You can use the addr2line tool to obtain the specific code line and rectify the fault. 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ci **Figure 4** Adding a check value to the node header information 55e41f4b71Sopenharmony_ci 56e41f4b71Sopenharmony_ci  57e41f4b71Sopenharmony_ci 58e41f4b71Sopenharmony_ci When heap memory is released by **free**, the memory block is not released immediately. Instead, the magic number 0xFE is written into the memory block, which is then placed in the free queue to prevent the memory block from being allocated by **malloc** within a certain period of time. When a wild pointer or **use-after-free** operation is performed to read the memory, an exception can be detected. However, this mechanism does not apply to write operations. 59e41f4b71Sopenharmony_ci 60e41f4b71Sopenharmony_ci **Figure 5** Process of releasing memory 61e41f4b71Sopenharmony_ci 62e41f4b71Sopenharmony_ci  63e41f4b71Sopenharmony_ci 64e41f4b71Sopenharmony_ci 65e41f4b71Sopenharmony_ci 66e41f4b71Sopenharmony_ci- Requested memory greater than 0x1c000 bytes 67e41f4b71Sopenharmony_ci 68e41f4b71Sopenharmony_ci When the requested memory is greater than 0x1c000 bytes, **malloc** uses **mmap** to allocate memory. 69e41f4b71Sopenharmony_ci 70e41f4b71Sopenharmony_ci When **mmap** is used to allocate a large memory block, one more page is allocated at the start and end of the memory region. The current **PAGE_SIZE** of each page is **0x1000**. The permissions of the two pages are set to **PROT_NONE** (no read or write permission) by using the **mprotect** API to prevent out-of-bounds read and write of memory. If out-of-bounds read and write of memory occurs, the user program becomes abnormal because the user does not have the read or write permission. The code logic can be identified based on the abnormal call stack information. 71e41f4b71Sopenharmony_ci 72e41f4b71Sopenharmony_ci **Figure 6** Layout of the memory allocated by using the **mmap** mechanism of **malloc** 73e41f4b71Sopenharmony_ci 74e41f4b71Sopenharmony_ci  75e41f4b71Sopenharmony_ci 76e41f4b71Sopenharmony_ci### Usage Guide 77e41f4b71Sopenharmony_ci#### Available APIs 78e41f4b71Sopenharmony_ci 79e41f4b71Sopenharmony_ci 80e41f4b71Sopenharmony_ci **Table 1** Memory debugging APIs 81e41f4b71Sopenharmony_ci 82e41f4b71Sopenharmony_ci| API| Description| 83e41f4b71Sopenharmony_ci| -------- | -------- | 84e41f4b71Sopenharmony_ci| mem_check_init | Initializes the memory check module.| 85e41f4b71Sopenharmony_ci| watch_mem | Obtains the thread-level heap memory usage.| 86e41f4b71Sopenharmony_ci| check_leak | Checks for heap memory leaks.| 87e41f4b71Sopenharmony_ci| check_heap_integrity | Checks the heap memory integrity.| 88e41f4b71Sopenharmony_ci| backtrace | Obtains the address information of the call stack.| 89e41f4b71Sopenharmony_ci| backtrace_symbols | Obtains symbol information based on address information.| 90e41f4b71Sopenharmony_ci| print_trace | Prints call stack information.| 91e41f4b71Sopenharmony_ci 92e41f4b71Sopenharmony_ci 93e41f4b71Sopenharmony_ci **Table 2** Call stack backtracking APIs 94e41f4b71Sopenharmony_ci 95e41f4b71Sopenharmony_ci| API| Description| 96e41f4b71Sopenharmony_ci| -------- | -------- | 97e41f4b71Sopenharmony_ci| backtrace | Obtains the address information of the call stack.| 98e41f4b71Sopenharmony_ci| backtrace_symbols | Obtains symbol information based on address information.| 99e41f4b71Sopenharmony_ci| print_trace | Prints call stack information.| 100e41f4b71Sopenharmony_ci 101e41f4b71Sopenharmony_ci### How to Use 102e41f4b71Sopenharmony_ci 103e41f4b71Sopenharmony_ci 104e41f4b71Sopenharmony_ciBy default, the OpenHarmony debug version is compiled when a project is built. The libc library of the debug version has integrated the APIs for memory debugging. You can enable memory debugging as required. 105e41f4b71Sopenharmony_ci 106e41f4b71Sopenharmony_ci 107e41f4b71Sopenharmony_ciYou can perform heap memory debugging by using either of the following: 108e41f4b71Sopenharmony_ci 109e41f4b71Sopenharmony_ci 110e41f4b71Sopenharmony_ci- API: By calling APIs, you can accurately check the heap memory information of a specific code logic segment. However, you have to modify user code. 111e41f4b71Sopenharmony_ci 112e41f4b71Sopenharmony_ci- CLI: By using the CLI, you do not need to modify user code. However, you cannot accurately check the heap memory information of a specific logic segment. 113e41f4b71Sopenharmony_ci 114e41f4b71Sopenharmony_ci 115e41f4b71Sopenharmony_ci> **NOTE**<br> 116e41f4b71Sopenharmony_ci> After memory debugging is enabled, a heap memory leak check and a heap memory integrity check will be performed by default when a process exits. If memory debugging is disabled, the heap memory statistics, heap memory leak check, and heap memory integrity check cannot be enabled, and there is no response to the calling of any debug API. 117e41f4b71Sopenharmony_ci 118e41f4b71Sopenharmony_ci 119e41f4b71Sopenharmony_ci 120e41f4b71Sopenharmony_ci 121e41f4b71Sopenharmony_ci#### Calling APIs 122e41f4b71Sopenharmony_ci 123e41f4b71Sopenharmony_ci 124e41f4b71Sopenharmony_ci##### Sample Code 125e41f4b71Sopenharmony_ci 126e41f4b71Sopenharmony_ciThe sample code explicitly calls the related APIs of the memory debugging module to check the memory. 127e41f4b71Sopenharmony_ci 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci```c 130e41f4b71Sopenharmony_ci#include <pthread.h> 131e41f4b71Sopenharmony_ci#include <stdlib.h> 132e41f4b71Sopenharmony_ci#include <stdio.h> 133e41f4b71Sopenharmony_ci#include <debug.h> // Header file that includes the declaration of the memory debugging APIs 134e41f4b71Sopenharmony_ci 135e41f4b71Sopenharmony_ci#define MALLOC_LEAK_SIZE 0x300 136e41f4b71Sopenharmony_ci 137e41f4b71Sopenharmony_civoid func(void) 138e41f4b71Sopenharmony_ci{ 139e41f4b71Sopenharmony_ci char *ptr = malloc(MALLOC_LEAK_SIZE); 140e41f4b71Sopenharmony_ci memset(ptr, '3', MALLOC_LEAK_SIZE); 141e41f4b71Sopenharmony_ci} 142e41f4b71Sopenharmony_ci 143e41f4b71Sopenharmony_ciint main() 144e41f4b71Sopenharmony_ci{ 145e41f4b71Sopenharmony_ci mem_check_init(NULL); // Output the memory debugging information through the serial port. This function must be called before the user program requests the heap memory for the first time (generally called at the entry of the main function). Otherwise, the debugging information is inaccurate. 146e41f4b71Sopenharmony_ci // mem_check_init("/storage/mem_debug.txt"); // Output the memory debugging information to the /storage/mem_debug.txt file. If the file fails to be created, output the information through the serial port. 147e41f4b71Sopenharmony_ci char *ptr = malloc(MALLOC_LEAK_SIZE); 148e41f4b71Sopenharmony_ci memset(ptr, '1', MALLOC_LEAK_SIZE); 149e41f4b71Sopenharmony_ci 150e41f4b71Sopenharmony_ci watch_mem(); // Obtain the thread-level memory statistics in the current code. 151e41f4b71Sopenharmony_ci func(); 152e41f4b71Sopenharmony_ci check_heap_integrity(); // Check the integrity of the heap memory nodes. 153e41f4b71Sopenharmony_ci check_leak(); // Check whether a heap memory leak occurs in the current code. (Generally, the check result is accurate before the application exits. If the check is performed after the calling of malloc and before the calling of free, the result is inaccurate.) 154e41f4b71Sopenharmony_ci return 0; 155e41f4b71Sopenharmony_ci} 156e41f4b71Sopenharmony_ci``` 157e41f4b71Sopenharmony_ci 158e41f4b71Sopenharmony_ci 159e41f4b71Sopenharmony_ci##### Compilation 160e41f4b71Sopenharmony_ci 161e41f4b71Sopenharmony_ci 162e41f4b71Sopenharmony_ci``` 163e41f4b71Sopenharmony_ci$ clang -o mem_check mem_check.c -funwind-tables -rdynamic -g -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos --sysroot=/home/<user-name>/directory/out/hispark_taurus/ipcamera_hispark_taurus/sysroot $(clang -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos -print-file-name=libunwind.a) 164e41f4b71Sopenharmony_ci``` 165e41f4b71Sopenharmony_ci 166e41f4b71Sopenharmony_ci 167e41f4b71Sopenharmony_ci> **NOTE** 168e41f4b71Sopenharmony_ci> 169e41f4b71Sopenharmony_ci> - In this example, the compiler path is written into an environment variable in the **.bashrc** file. 170e41f4b71Sopenharmony_ci> 171e41f4b71Sopenharmony_ci> - When compiling user programs and required libraries, add the option **-funwind-tables -rdynamic -g** for stack backtracking. 172e41f4b71Sopenharmony_ci> 173e41f4b71Sopenharmony_ci> - The **-mfloat-abi=softfp**, **-mcpu=cortex-a7**, and **-mfpu=neon-vfpv4** options specify the floating-point calculation optimization, chip architecture, and FPU, which must be the same as the compilation options used by the libc library. Otherwise, the libc library file cannot be found during the link time. 174e41f4b71Sopenharmony_ci> 175e41f4b71Sopenharmony_ci> - **-target arm-liteos** specifies the path of the library files related to the compiler. 176e41f4b71Sopenharmony_ci> 177e41f4b71Sopenharmony_ci> - **--sysroot=/home/<user-name>/harmony/out/hispark_taurus/ipcamera_hispark_taurus/sysroot** specifies the root directory of the compiler library files. In this example, the OpenHarmony project code is stored in **/home/<user-name>/harmony**. The **out/hispark_taurus/ipcamera_hispark_taurus** directory indicates the product specified by the **hb set** command during compilation. In this example, **ipcamera_hispark_taurus** is the product specified. 178e41f4b71Sopenharmony_ci> 179e41f4b71Sopenharmony_ci> - **$(clang -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos -print-file-name=libunwind.a)** specifies the path of the unwind library. 180e41f4b71Sopenharmony_ci 181e41f4b71Sopenharmony_ci 182e41f4b71Sopenharmony_ci##### Debugging Information 183e41f4b71Sopenharmony_ci 184e41f4b71Sopenharmony_ci 185e41f4b71Sopenharmony_ci``` 186e41f4b71Sopenharmony_ciOHOS # ./mem_check 187e41f4b71Sopenharmony_ciOHOS # 188e41f4b71Sopenharmony_ci==PID:4== Heap memory statistics(bytes): // Heap memory statistics 189e41f4b71Sopenharmony_ci [Check point]: // Call stack of the check point 190e41f4b71Sopenharmony_ci #00: <main+0x38>[0x86c] -> mem_check 191e41f4b71Sopenharmony_ci #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so 192e41f4b71Sopenharmony_ci 193e41f4b71Sopenharmony_ci [TID: 18, Used: 0x320] // The heap memory is occupied by thread No. 18. The current process has only one thread. 194e41f4b71Sopenharmony_ci 195e41f4b71Sopenharmony_ci==PID:4== Total heap: 0x320 byte(s), Peak: 0x320 byte(s) 196e41f4b71Sopenharmony_ci 197e41f4b71Sopenharmony_ciCheck heap integrity ok! // Heap memory integrity check 198e41f4b71Sopenharmony_ci 199e41f4b71Sopenharmony_ci==PID:4== Detected memory leak(s): // Memory leak information and call stack 200e41f4b71Sopenharmony_ci [Check point]: 201e41f4b71Sopenharmony_ci #00: <check_leak+0x1c4>[0x2da4c] -> /lib/libc.so 202e41f4b71Sopenharmony_ci #01: <main+0x44>[0x878] -> mem_check 203e41f4b71Sopenharmony_ci 204e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 205e41f4b71Sopenharmony_ci #00: <main+0x1c>[0x850] -> mem_check 206e41f4b71Sopenharmony_ci #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so 207e41f4b71Sopenharmony_ci 208e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 209e41f4b71Sopenharmony_ci #00: <func+0x14>[0x810] -> mem_check 210e41f4b71Sopenharmony_ci #01: <main+0x3c>[0x870] -> mem_check 211e41f4b71Sopenharmony_ci #02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so 212e41f4b71Sopenharmony_ci 213e41f4b71Sopenharmony_ci==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). 214e41f4b71Sopenharmony_ci 215e41f4b71Sopenharmony_ci==PID:4== Detected memory leak(s): 216e41f4b71Sopenharmony_ci [Check point]: 217e41f4b71Sopenharmony_ci #00: <check_leak+0x1c4>[0x2da4c] -> /lib/libc.so 218e41f4b71Sopenharmony_ci #01: <exit+0x28>[0x111ec] -> /lib/libc.so 219e41f4b71Sopenharmony_ci 220e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 221e41f4b71Sopenharmony_ci #00: <main+0x1c>[0x850] -> mem_check 222e41f4b71Sopenharmony_ci #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so 223e41f4b71Sopenharmony_ci 224e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 225e41f4b71Sopenharmony_ci #00: <func+0x14>[0x810] -> mem_check 226e41f4b71Sopenharmony_ci #01: <main+0x3c>[0x870] -> mem_check 227e41f4b71Sopenharmony_ci #02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so 228e41f4b71Sopenharmony_ci 229e41f4b71Sopenharmony_ci==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). 230e41f4b71Sopenharmony_ci 231e41f4b71Sopenharmony_ciCheck heap integrity ok! 232e41f4b71Sopenharmony_ci``` 233e41f4b71Sopenharmony_ci 234e41f4b71Sopenharmony_ci 235e41f4b71Sopenharmony_ci##### Call Stack Parsing 236e41f4b71Sopenharmony_ci 237e41f4b71Sopenharmony_ciThe **parse_mem_info.sh** script in **kernel/liteos_a/tools/scripts/parse_memory/** can be used to parse the call stack. You can use the script to convert the debug information into specific source code line number. In the following command, **mem_debug.txt** stores the memory debugging information, and **elf1** and **elf2** are the executable and linkable format (ELF) files to parse. 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_ci 240e41f4b71Sopenharmony_ci``` 241e41f4b71Sopenharmony_ci$ ./parse_mem_info.sh mem_debug.txt elf1 elf2 elf3 ... 242e41f4b71Sopenharmony_ci``` 243e41f4b71Sopenharmony_ci 244e41f4b71Sopenharmony_ciExample: 245e41f4b71Sopenharmony_ci 246e41f4b71Sopenharmony_ci 247e41f4b71Sopenharmony_ci``` 248e41f4b71Sopenharmony_ci$ ./parse_mem_info.sh mem_debug.txt mem_check 249e41f4b71Sopenharmony_ciCompiler is [gcc/llvm]: llvm 250e41f4b71Sopenharmony_ciNow using addr2line ... 251e41f4b71Sopenharmony_ci 252e41f4b71Sopenharmony_ci==PID:4== Heap memory statistics(bytes): 253e41f4b71Sopenharmony_ci [Check point]: 254e41f4b71Sopenharmony_ci #00: <main+0x38>[0x86c] at /usr1/xxx/TEST_ELF/mem_check.c:22 255e41f4b71Sopenharmony_ci #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so 256e41f4b71Sopenharmony_ci 257e41f4b71Sopenharmony_ci [TID: 18, Used: 0x320] 258e41f4b71Sopenharmony_ci 259e41f4b71Sopenharmony_ci==PID:4== Total heap: 0x320 byte(s), Peak: 0x320 byte(s) 260e41f4b71Sopenharmony_ci 261e41f4b71Sopenharmony_ciCheck heap integrity ok! 262e41f4b71Sopenharmony_ci 263e41f4b71Sopenharmony_ci==PID:4== Detected memory leak(s): 264e41f4b71Sopenharmony_ci [Check point]: 265e41f4b71Sopenharmony_ci #00: <check_leak+0x1c4>[0x2da4c] -> /lib/libc.so 266e41f4b71Sopenharmony_ci #01: <main+0x44>[0x878] at /usr1/xxx/TEST_ELF/mem_check.c:28 267e41f4b71Sopenharmony_ci 268e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 269e41f4b71Sopenharmony_ci #00: <main+0x1c>[0x850] at /usr1/xxx/TEST_ELF/mem_check.c:17 270e41f4b71Sopenharmony_ci #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so 271e41f4b71Sopenharmony_ci 272e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 273e41f4b71Sopenharmony_ci #00: <func+0x14>[0x810] at /usr1/xxx/TEST_ELF/mem_check.c:9 274e41f4b71Sopenharmony_ci #01: <main+0x3c>[0x870] at /usr1/xxx/TEST_ELF/mem_check.c:24 275e41f4b71Sopenharmony_ci #02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so 276e41f4b71Sopenharmony_ci 277e41f4b71Sopenharmony_ci==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). 278e41f4b71Sopenharmony_ci``` 279e41f4b71Sopenharmony_ci 280e41f4b71Sopenharmony_ci#### Using the CLI 281e41f4b71Sopenharmony_ci 282e41f4b71Sopenharmony_ci 283e41f4b71Sopenharmony_ciIn addition to calling APIs to check the memory used by user-mode processes, you can run CLI commands to collect memory statistics, check for memory leaks, and check memory integrity. 284e41f4b71Sopenharmony_ci 285e41f4b71Sopenharmony_ci``` 286e41f4b71Sopenharmony_ci--mwatch: initializes memory debugging, registers signals, and outputs memory debugging information through the serial port. 287e41f4b71Sopenharmony_ci--mrecord <f_path>: initializes memory debugging, registers signals, and saves the memory debugging information to the f_path file. If the f_path file fails to be created, output the memory debugging information through the serial port. 288e41f4b71Sopenharmony_ci``` 289e41f4b71Sopenharmony_ci 290e41f4b71Sopenharmony_ci 291e41f4b71Sopenharmony_ciIf the process to debug does not exit, you can use the signal mechanism to obtain the corresponding information: 292e41f4b71Sopenharmony_ci 293e41f4b71Sopenharmony_ci``` 294e41f4b71Sopenharmony_cikill -35 <pid> # Check the thread-level heap memory usage. 295e41f4b71Sopenharmony_cikill -36 <pid> # Check for heap memory leaks. 296e41f4b71Sopenharmony_cikill -37 <pid> # Check whether the head node of the heap memory is complete. 297e41f4b71Sopenharmony_ci``` 298e41f4b71Sopenharmony_ci 299e41f4b71Sopenharmony_ci 300e41f4b71Sopenharmony_ci##### Sample Code 301e41f4b71Sopenharmony_ci 302e41f4b71Sopenharmony_ciThe sample code constructs a memory problem and uses the command line to perform memory debugging. 303e41f4b71Sopenharmony_ci 304e41f4b71Sopenharmony_ci 305e41f4b71Sopenharmony_ci```c 306e41f4b71Sopenharmony_ci#include <pthread.h> 307e41f4b71Sopenharmony_ci#include <stdlib.h> 308e41f4b71Sopenharmony_ci#include <stdio.h> 309e41f4b71Sopenharmony_ci 310e41f4b71Sopenharmony_ci#define MALLOC_LEAK_SIZE 0x300 311e41f4b71Sopenharmony_ci 312e41f4b71Sopenharmony_civoid func(void) 313e41f4b71Sopenharmony_ci{ 314e41f4b71Sopenharmony_ci char *ptr = malloc(MALLOC_LEAK_SIZE); 315e41f4b71Sopenharmony_ci memset(ptr, '3', MALLOC_LEAK_SIZE); 316e41f4b71Sopenharmony_ci} 317e41f4b71Sopenharmony_ci 318e41f4b71Sopenharmony_ciint main() 319e41f4b71Sopenharmony_ci{ 320e41f4b71Sopenharmony_ci char *ptr = malloc(MALLOC_LEAK_SIZE); 321e41f4b71Sopenharmony_ci memset(ptr, '1', MALLOC_LEAK_SIZE); 322e41f4b71Sopenharmony_ci func(); 323e41f4b71Sopenharmony_ci while (1); 324e41f4b71Sopenharmony_ci} 325e41f4b71Sopenharmony_ci``` 326e41f4b71Sopenharmony_ci 327e41f4b71Sopenharmony_ci 328e41f4b71Sopenharmony_ci##### Compilation 329e41f4b71Sopenharmony_ci 330e41f4b71Sopenharmony_ciFor details, see [Compilation](#compilation). 331e41f4b71Sopenharmony_ci 332e41f4b71Sopenharmony_ci 333e41f4b71Sopenharmony_ci##### Running the mwatch Command 334e41f4b71Sopenharmony_ci 335e41f4b71Sopenharmony_ci 336e41f4b71Sopenharmony_ci``` 337e41f4b71Sopenharmony_ciOHOS # ./mem_check --mwatch // Run the task command to obtain the mem_check process PID, which is 4. 338e41f4b71Sopenharmony_ciOHOS # 339e41f4b71Sopenharmony_ciOHOS # kill -35 4 // Check heap memory statistics. 340e41f4b71Sopenharmony_ciOHOS # 341e41f4b71Sopenharmony_ci==PID:4== Heap memory statistics(bytes): 342e41f4b71Sopenharmony_ci [Check point]: 343e41f4b71Sopenharmony_ci #00: <arm_signal_process+0x5c>[0x58dfc] -> /lib/libc.so 344e41f4b71Sopenharmony_ci 345e41f4b71Sopenharmony_ci [TID: 18, Used: 0x640] 346e41f4b71Sopenharmony_ci 347e41f4b71Sopenharmony_ci==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) 348e41f4b71Sopenharmony_ci 349e41f4b71Sopenharmony_ciOHOS # kill -36 4 // Check for heap memory leaks. 350e41f4b71Sopenharmony_ciOHOS # 351e41f4b71Sopenharmony_ci==PID:4== Detected memory leak(s): 352e41f4b71Sopenharmony_ci [Check point]: 353e41f4b71Sopenharmony_ci #00: <check_leak+0x1c4>[0x2da4c] -> /lib/libc.so 354e41f4b71Sopenharmony_ci #01: <arm_signal_process+0x5c>[0x58dfc] -> /lib/libc.so 355e41f4b71Sopenharmony_ci 356e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 357e41f4b71Sopenharmony_ci #00: <main+0x14>[0x724] -> mem_check 358e41f4b71Sopenharmony_ci #01: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so 359e41f4b71Sopenharmony_ci 360e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 361e41f4b71Sopenharmony_ci #00: <func+0x14>[0x6ec] -> mem_check 362e41f4b71Sopenharmony_ci #01: <main+0x30>[0x740] -> mem_check 363e41f4b71Sopenharmony_ci #02: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so 364e41f4b71Sopenharmony_ci 365e41f4b71Sopenharmony_ci==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). 366e41f4b71Sopenharmony_ci 367e41f4b71Sopenharmony_ciOHOS # kill -37 4 // Check the integrity of the head node of the heap memory. 368e41f4b71Sopenharmony_ciOHOS # 369e41f4b71Sopenharmony_ciCheck heap integrity ok! 370e41f4b71Sopenharmony_ci``` 371e41f4b71Sopenharmony_ci 372e41f4b71Sopenharmony_ci 373e41f4b71Sopenharmony_ci##### Call Stack Parsing 374e41f4b71Sopenharmony_ci 375e41f4b71Sopenharmony_ciSave the debugging information to the **test.txt** file and use the script to parse the information to obtain the number of the line where the memory leak occurs. 376e41f4b71Sopenharmony_ci 377e41f4b71Sopenharmony_ci 378e41f4b71Sopenharmony_ci``` 379e41f4b71Sopenharmony_ci$ ./parse_mem_info.sh test.txt mem_check 380e41f4b71Sopenharmony_ciCompiler is [gcc/llvm]: llvm 381e41f4b71Sopenharmony_ciNow using addr2line ... 382e41f4b71Sopenharmony_ci 383e41f4b71Sopenharmony_ci==PID:4== Detected memory leak(s): 384e41f4b71Sopenharmony_ci [Check point]: 385e41f4b71Sopenharmony_ci #00: <check_leak+0x1c4>[0x2da4c] -> /lib/libc.so 386e41f4b71Sopenharmony_ci #01: <arm_signal_process+0x5c>[0x58dfc] -> /lib/libc.so 387e41f4b71Sopenharmony_ci 388e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 389e41f4b71Sopenharmony_ci #00: <main+0x14>[0x724] at /usr1/xxx/TEST_ELF/mem_check.c:14 390e41f4b71Sopenharmony_ci #01: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so 391e41f4b71Sopenharmony_ci 392e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 393e41f4b71Sopenharmony_ci #00: <func+0x14>[0x6ec] at /usr1/xxx/TEST_ELF/mem_check.c:8 394e41f4b71Sopenharmony_ci #01: <main+0x30>[0x740] at /usr1/xxx/TEST_ELF/mem_check.c:19 395e41f4b71Sopenharmony_ci #02: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so 396e41f4b71Sopenharmony_ci 397e41f4b71Sopenharmony_ci==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). 398e41f4b71Sopenharmony_ci``` 399e41f4b71Sopenharmony_ci 400e41f4b71Sopenharmony_ci 401e41f4b71Sopenharmony_ci##### Running the mrecord Command 402e41f4b71Sopenharmony_ci 403e41f4b71Sopenharmony_ci1. Run the user program and specify the path of the file that stores the memory debugging information. 404e41f4b71Sopenharmony_ci 405e41f4b71Sopenharmony_ci ``` 406e41f4b71Sopenharmony_ci OHOS # ./mem_check --mrecord /storage/check.txt 407e41f4b71Sopenharmony_ci ``` 408e41f4b71Sopenharmony_ci 409e41f4b71Sopenharmony_ci2. Run the **kill -35 <*pid*>** command to collect statistics on the memory information. The information is exported to a file. Run the **cat** command to view the information. 410e41f4b71Sopenharmony_ci 411e41f4b71Sopenharmony_ci ``` 412e41f4b71Sopenharmony_ci OHOS # kill -35 4 413e41f4b71Sopenharmony_ci OHOS # Memory statistics information saved in /storage/pid(4)_check.txt 414e41f4b71Sopenharmony_ci 415e41f4b71Sopenharmony_ci OHOS # cat /storage/pid(4)_check.txt 416e41f4b71Sopenharmony_ci 417e41f4b71Sopenharmony_ci ==PID:4== Heap memory statistics(bytes): 418e41f4b71Sopenharmony_ci [Check point]: 419e41f4b71Sopenharmony_ci #00: <arm_signal_process+0x5c>[0x5973c] -> /lib/libc.so 420e41f4b71Sopenharmony_ci 421e41f4b71Sopenharmony_ci [TID: 18, Used: 0x640] 422e41f4b71Sopenharmony_ci 423e41f4b71Sopenharmony_ci ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) 424e41f4b71Sopenharmony_ci ``` 425e41f4b71Sopenharmony_ci 426e41f4b71Sopenharmony_ci3. Run the **kill -36 <*pid*>** command to check memory integrity. The information is exported to a file. Run the **cat** command to view the information. 427e41f4b71Sopenharmony_ci 428e41f4b71Sopenharmony_ci ``` 429e41f4b71Sopenharmony_ci OHOS # kill -36 4 430e41f4b71Sopenharmony_ci OHOS # Leak check information saved in /storage/pid(4)_check.txt 431e41f4b71Sopenharmony_ci 432e41f4b71Sopenharmony_ci OHOS # cat /storage/pid(4)_check.txt 433e41f4b71Sopenharmony_ci 434e41f4b71Sopenharmony_ci ==PID:4== Heap memory statistics(bytes): 435e41f4b71Sopenharmony_ci [Check point]: 436e41f4b71Sopenharmony_ci #00: <arm_signal_process+0x5c>[0x5973c] -> /lib/libc.so 437e41f4b71Sopenharmony_ci 438e41f4b71Sopenharmony_ci [TID: 18, Used: 0x640] 439e41f4b71Sopenharmony_ci 440e41f4b71Sopenharmony_ci ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) 441e41f4b71Sopenharmony_ci 442e41f4b71Sopenharmony_ci ==PID:4== Detected memory leak(s): 443e41f4b71Sopenharmony_ci [Check point]: 444e41f4b71Sopenharmony_ci #00: <check_leak+0x1c4>[0x2e38c] -> /lib/libc.so 445e41f4b71Sopenharmony_ci #01: <arm_signal_process+0x5c>[0x5973c] -> /lib/libc.so 446e41f4b71Sopenharmony_ci 447e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 448e41f4b71Sopenharmony_ci #00: <main+0x14>[0x724] -> mem_check 449e41f4b71Sopenharmony_ci #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so 450e41f4b71Sopenharmony_ci 451e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 452e41f4b71Sopenharmony_ci #00: <func+0x14>[0x6ec] -> mem_check 453e41f4b71Sopenharmony_ci #01: <main+0x30>[0x740] -> mem_check 454e41f4b71Sopenharmony_ci #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so 455e41f4b71Sopenharmony_ci 456e41f4b71Sopenharmony_ci ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). 457e41f4b71Sopenharmony_ci ``` 458e41f4b71Sopenharmony_ci 459e41f4b71Sopenharmony_ci4. Run the **kill -9 <*pid*>** command to kill the current process. After the process exits, a memory integrity check is performed by default. The check result is output to a file. You can run the **cat** command to view it. 460e41f4b71Sopenharmony_ci 461e41f4b71Sopenharmony_ci ``` 462e41f4b71Sopenharmony_ci OHOS # kill -9 4 463e41f4b71Sopenharmony_ci OHOS # Leak check information saved in /storage/pid(4)_check.txt 464e41f4b71Sopenharmony_ci 465e41f4b71Sopenharmony_ci Check heap integrity ok! 466e41f4b71Sopenharmony_ci 467e41f4b71Sopenharmony_ci OHOS # cat /storage/pid(4)_check.txt 468e41f4b71Sopenharmony_ci OHOS # 469e41f4b71Sopenharmony_ci ==PID:4== Heap memory statistics(bytes): 470e41f4b71Sopenharmony_ci [Check point]: 471e41f4b71Sopenharmony_ci #00: <arm_signal_process+0x5c>[0x5973c] -> /lib/libc.so 472e41f4b71Sopenharmony_ci 473e41f4b71Sopenharmony_ci [TID: 18, Used: 0x640] 474e41f4b71Sopenharmony_ci 475e41f4b71Sopenharmony_ci ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) 476e41f4b71Sopenharmony_ci 477e41f4b71Sopenharmony_ci ==PID:4== Detected memory leak(s): 478e41f4b71Sopenharmony_ci [Check point]: 479e41f4b71Sopenharmony_ci #00: <check_leak+0x1c4>[0x2e38c] -> /lib/libc.so 480e41f4b71Sopenharmony_ci #01: <arm_signal_process+0x5c>[0x5973c] -> /lib/libc.so 481e41f4b71Sopenharmony_ci 482e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 483e41f4b71Sopenharmony_ci #00: <main+0x14>[0x724] -> mem_check 484e41f4b71Sopenharmony_ci #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so 485e41f4b71Sopenharmony_ci 486e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 487e41f4b71Sopenharmony_ci #00: <func+0x14>[0x6ec] -> mem_check 488e41f4b71Sopenharmony_ci #01: <main+0x30>[0x740] -> mem_check 489e41f4b71Sopenharmony_ci #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so 490e41f4b71Sopenharmony_ci 491e41f4b71Sopenharmony_ci ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). 492e41f4b71Sopenharmony_ci 493e41f4b71Sopenharmony_ci ==PID:4== Detected memory leak(s): 494e41f4b71Sopenharmony_ci [Check point]: 495e41f4b71Sopenharmony_ci #00: <check_leak+0x1c4>[0x2e38c] -> /lib/libc.so 496e41f4b71Sopenharmony_ci #01: <exit+0x28>[0x11b2c] -> /lib/libc.so 497e41f4b71Sopenharmony_ci 498e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 499e41f4b71Sopenharmony_ci #00: <main+0x14>[0x724] -> mem_check 500e41f4b71Sopenharmony_ci #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so 501e41f4b71Sopenharmony_ci 502e41f4b71Sopenharmony_ci [TID:18 Leak:0x320 byte(s)] Allocated from: 503e41f4b71Sopenharmony_ci #00: <func+0x14>[0x6ec] -> mem_check 504e41f4b71Sopenharmony_ci #01: <main+0x30>[0x740] -> mem_check 505e41f4b71Sopenharmony_ci #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so 506e41f4b71Sopenharmony_ci 507e41f4b71Sopenharmony_ci ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). 508e41f4b71Sopenharmony_ci ``` 509e41f4b71Sopenharmony_ci 510e41f4b71Sopenharmony_ci> **NOTE**<br> 511e41f4b71Sopenharmony_ci> The preceding information recorded gradually is added to the file specified during initialization. Therefore, running the **cat** command can also display the historical information in the file. 512e41f4b71Sopenharmony_ci## Common Problems 513e41f4b71Sopenharmony_ci 514e41f4b71Sopenharmony_ci 515e41f4b71Sopenharmony_ci### Use After Free (UAF) 516e41f4b71Sopenharmony_ci 517e41f4b71Sopenharmony_ci- Requested memory less than or equal to 0x1c000 bytes: 518e41f4b71Sopenharmony_ci 519e41f4b71Sopenharmony_ci Read operation: If the magic number (0xFEFEFEFE) is read from the memory block released, UAF occurs. 520e41f4b71Sopenharmony_ci 521e41f4b71Sopenharmony_ci > **NOTE** 522e41f4b71Sopenharmony_ci > 523e41f4b71Sopenharmony_ci > After **free** is called, the heap memory will not be released to the heap memory pool immediately. Instead, the heap memory is placed in a queue with a fixed length and filled with the magic number 0xFE. When the queue is full, the memory block first placed in the queue is released to the heap memory pool first. 524e41f4b71Sopenharmony_ci 525e41f4b71Sopenharmony_ci Write operation: The memory debugging module cannot detect UAF errors from write operations. 526e41f4b71Sopenharmony_ci 527e41f4b71Sopenharmony_ci 528e41f4b71Sopenharmony_ci- Requested memory block greater than 0x1c000 bytes: 529e41f4b71Sopenharmony_ci 530e41f4b71Sopenharmony_ci The heap memory greater than 0x1c000 bytes must be requested by calling the **mmap** API via **malloc**. If the heap memory is accessed after being released, the user program will become abnormal (because the memory region has been unmapped). 531e41f4b71Sopenharmony_ci 532e41f4b71Sopenharmony_ci 533e41f4b71Sopenharmony_ci### Double Free 534e41f4b71Sopenharmony_ci 535e41f4b71Sopenharmony_ciDouble free errors occur when **free()** is called more than once with the same memory address as an argument. When a double free error occurs, the user program exits unexpectedly. 536e41f4b71Sopenharmony_ci 537e41f4b71Sopenharmony_ci 538e41f4b71Sopenharmony_ci### Heap Memory Node Corrupted 539e41f4b71Sopenharmony_ci 540e41f4b71Sopenharmony_ci- Requested memory block less than or equal to 0x1c000 bytes: 541e41f4b71Sopenharmony_ci 542e41f4b71Sopenharmony_ci When a heap memory node is corrupted, the user program exits unexpectedly, and the call stack that requests the heap memory of the node corrupted is output. The memory debugging module, however, cannot debug the memory corrupted by a wild pointer. For example, if the user program mem_check has heap memory overwriting, you can use the command line to obtain the possible location of the memory corruption. 543e41f4b71Sopenharmony_ci 544e41f4b71Sopenharmony_ci 545e41f4b71Sopenharmony_ci ``` 546e41f4b71Sopenharmony_ci OHOS # ./mem_check --mwatch 547e41f4b71Sopenharmony_ci OHOS # 548e41f4b71Sopenharmony_ci ==PID:6== Memory integrity information: 549e41f4b71Sopenharmony_ci [TID:28 allocated addr: 0x272e1ea0, size: 0x120] The possible attacker was allocated from: 550e41f4b71Sopenharmony_ci #00: <malloc+0x808>[0x640e8] -> /lib/libc.so 551e41f4b71Sopenharmony_ci #01: <threadFunc1+0x7c>[0x21d0] -> mem_check 552e41f4b71Sopenharmony_ci ``` 553e41f4b71Sopenharmony_ci 554e41f4b71Sopenharmony_ci You can use the call stack parsing script to parse the call stack information. 555e41f4b71Sopenharmony_ci 556e41f4b71Sopenharmony_ci- Requested memory block greater than 0x1c000 bytes: 557e41f4b71Sopenharmony_ci 558e41f4b71Sopenharmony_ci When a large memory block (greater than 0x1c000 bytes) is requested by calling the **mmap** API via **malloc**, one more page of **PAGE_SIZE** is allocated at the start and end of the memory region. The two pages are neither readable nor writeable. Any read or write operation to the pages may cause an exception of the user program. 559