Liteos中backtrace使用

在 LiteOS(特别是 LiteOS-M,用于 OpenHarmony 轻量系统) 中,backtrace(堆栈回溯)功能用于在调试、异常或死机时打印当前任务的函数调用链,帮助开发者快速定位问题源头。
由于 LiteOS-M 面向资源受限的嵌入式设备(如 Cortex-M、RISC-V),它不依赖标准库的 execinfo.h,而是提供了内核原生的轻量级回溯机制。

核心接口

// 头文件
#include "los_backtrace.h"

// 函数原型
VOID LOS_BackTrace(VOID);
  • 功能:从当前执行点向上回溯调用栈,并通过内核日志(如 PRINTK)输出返回地址。

  • 无参数、无返回值,使用简单。

输出示例(RISC-V 地址):

Back trace:
0x40023456
0x4001ABCD
0x40008765
...

启用 backtrace 功能

开启宏定义,在kernel_liteos_m\target_config.h文件中,设置LOSCFG_BACKTRACE_TYPE:

#define LOSCFG_BACKTRACE 1

实现原理(简要)

LiteOS-M 的 backtrace 基于 栈帧遍历 或 LR(Link Register)链回溯:

Cortex-M:利用 MSP/PSP 栈中的 LR 寄存器值逐层回溯。

RISC-V:通过栈上保存的 ra(return address)寄存器回溯(需未被优化掉)。

每次回溯一个函数的返回地址(PC 值),直到栈底或达到最大深度。

若编译时开启高优化(如 -Os),可能内联函数或省略栈帧,导致回溯不完整。建议调试时使用 -O0 或 -fno-omit-frame-pointer。

使用场景

  1. 断言失败时自动打印堆栈
#include "los_backtrace.h"
#include "los_debug.h"

void __assert_func(const char *file, int line, const char *func, const char *failedexpr)
{
    PRINT_ERR("ASSERT FAILED: %s:%d in %s(), expr: %s\n", file, line, func, failedexpr);
    PRINTK("Call stack:\n");
    LOS_BackTrace();
    while (1); // 死循环,便于调试
}
  1. 在关键函数中手动触发回溯(调试用)
void critical_operation(void)
{
    if (error_detected) {
        PRINTK("Error! Call stack:\n");
        LOS_BackTrace();
    }
}

地址解析

LiteOS-M 不提供运行时符号解析,需离线工具配合 .elf 文件。

步骤:

  1. 获取编译生成的 ELF 文件(如 liteos_m.elf)

  2. 使用交叉工具链的 addr2line:

# RISC-V 示例
riscv-none-embed-addr2line -e out/L0_xts_demo/liteos_m.elf 0x40023456

# ARM 示例
arm-none-eabi-addr2line -e liteos_m.elf 0x08001234

输出示例:

my_function
/project/src/main.c:42

注意:不要尝试 #include <execinfo.h> —— LiteOS 不支持 glibc 的 backtrace!
如果你正在调试 LiteOS-M 死机问题,结合 LOS_BackTrace() + addr2line 是最高效的定位手段。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐