Trace Debugging

Basic Concepts

Trace debugging helps you learn about the kernel running process and the execution sequence of modules and tasks. With the information, you can better understand the code running process of the kernel and locate time sequence problems.

Working Principles

The kernel provides a framework to embed hooks in main processes of modules. You can register callback functions at the required hooks. When the kernel runs the corresponding process, the kernel proactively calls the Hook function to transfer key data of the current process to you.

Available APIs

The following table describes APIs available for the OpenHarmony trace module. For more details about the APIs, see the API reference.

Table 1 Trace module APIs

Category

API

Description

Registering a hook

LOS_HookReg

Registers a callback function at a specified hook.

Unregistering a hook

LOS_HookUnReg

Unregisters the callback function at the current hook.

Development Guidelines

How to Develop

The typical process for enabling trace debugging is as follows:

  1. Configure the macros related to the trace module.

    Modify the configuration in the target_config.h file.

    Parameter

    Description

    Value

    LOSCFG_DEBUG_HOOK

    Setting of the trace function

    0: disable; 1: enable

  2. Select the hooks for registering callback functions. For details about the hook types, see liteos_m/utils/internal/los_hook_types.h.

  3. Call LOS_HookReg to register functions.

Development Example

This example invokes the malloc and free APIs to allocate and release memory of different sizes and records the malloc and free behavior and time sequence.

Sample Code

The sample code is as follows:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "los_hook.h"

#define SIZE_512        512
#define SIZE_1K         1024
#define SIZE_2K         2048

/* Print the size of malloc when the callback function is invoked. */
void MallocRecord(void *pool, unsigned int size)
{
    printf("malloc size = %u\n", size);
    return;
}

/* Print the free pointer address when the callback function is invoked. */
void FreeRecord(void *pool, void *ptr)
{
    printf("free pool = 0x%x ptr = 0x%x\n", pool, ptr);
    return;
}

void TestTrace(void)
{
    char *pool1 = NULL;
    char *pool2 = NULL;
    char *pool3 = NULL;
    char *retptr = NULL;
    /* Allocate memory of different sizes to pool1, pool2, and pool3. */
    pool1 = (char *)malloc(SIZE_512);
    if (pool1 == NULL) {
        printf("pool1 malloc failed!\n");
        return;
    }
    retptr = memset(pool1, 'a', SIZE_512);
    if (retptr == NULL) {
        printf("pool1 memset failed!\n");
        return;
    }
    printf("pool1 addr = 0x%x *pool1[0] = %c\n", pool1, *pool1);

    pool2 = (char *)malloc(SIZE_1K);
    if (pool2 == NULL) {
        printf("pool2 malloc failed!\n");
        return;
    }
    retptr = memset(pool2, 'b', SIZE_1K);
    if (retptr == NULL) {
        printf("pool2 memset failed!\n");
        return;
    }
    printf("pool2 addr = 0x%x *pool2[0] = %c\n", pool2, *pool2);

    pool3 = (char *)malloc(SIZE_2K);
    if (pool3 == NULL) {
        printf("pool3 malloc failed!\n");
        return;
    }
    retptr = memset(pool3, 'c', SIZE_2K);
    if (retptr == NULL) {
        printf("pool3 memset failed!\n");
        return;
    }
    printf("pool3 addr = 0x%x *pool3[0] = %c\n", pool3, *pool3);

    /* Release pool3, pool1, and pool2 in sequence to check the time sequence of the callback functions. */
    free(pool3);
    free(pool1);
    free(pool2);

    return;
}
/* Before the trace module is used, callback functions are registered. Note that the return value of the callback functions is void. */
void InitTest(void)
{
    printf("init hook\n");
    /* Register the hook based on the trace information to be obtained. For details about the hook types, see liteos_m/utils/internal/los_hook_types.h. */.
    LOS_HookReg(LOS_HOOK_TYPE_MEM_ALLOC, MallocRecord);
    LOS_HookReg(LOS_HOOK_TYPE_MEM_FREE, FreeRecord);
    return;
}

Verification

The output is as follows:

init hook
malloc size = 512
pool1 addr = 0x20002f44 *pool1[0] = a
malloc size = 1024
pool2 addr = 0x2000314c *pool2[0] = b
malloc size = 2048
pool3 addr = 0x20003554 *pool3[0] = c
free pool = 0x200002a4 ptr = 0x20003554
free pool = 0x200002a4 ptr = 0x20002f44
free pool = 0x200002a4 ptr = 0x2000314c

According to the address information, the sequence of free is pool3, pool1, and pool2.