在rtems上手动实现backtrace

本文详细介绍了如何在RTEMS操作系统上手动实现backtrace功能,包括FP指针获取、调用栈打印、函数名打印、thumb模式下的处理,以及在RTEMS异常机制下的实现策略,特别讨论了在不同上下文中如何捕获和打印调用栈。
摘要由CSDN通过智能技术生成

在rtems上手动实现backtrace

由于rtems没有Linux那种crash自动打印调用栈的机制,故需要手动实现。调用栈的实现依赖于fp指针,通过fp可以找到每一级函数的栈帧,根据arm函数调用规范,在栈帧中保存着pc、sp、lr、fp等信息,因此可以将每一级的pc值打出来就是我们需要的调用栈了,通过addr2line工具可以将pc指针解析为对应的行号,从而帮助我们精确定位问题

FP指针的获取

-mapcs

首先添加这个参数,使编译出来的代码遵守apcs标准,也就是使函数的栈帧保持如下的样子

在这里插入图片描述

-fno-omit-frame-pointer

其次,添加这个参数,用来防止fp指针被优化掉

有了以上两个选项,就可以通过fp一层一层找到上一级函数的栈帧,pc、lr、sp、fp相对于栈帧首地址都是固定偏移,因此有了fp,所有信息都可以找到了

对于调用栈的获取,主要是获取每一级函数的pc指针,然后通过addr2line工具得到对应的代码行

调用栈打印不完整

需要添加编译选项

-O0

否则很多函数被优化成inline,几乎看不到调用的中间过程

函数名的打印

添加以下编译选项

-mpoke-function-name

添加之后,编译的时候,将会为每一个函数生成符号名,保存到与函数首地址紧挨的部分,例如:

               t0
                   .ascii "arm_poke_function_name", 0
                   .align
               t1
                   .word 0xff000000 + (t1 - t0)
               arm_poke_function_name
                   mov     ip, sp
                   stmfd   sp!, {fp, ip, lr, pc}
                   sub     fp, ip, #4

在函数的头部,将会存放一个word,值为0xff000000和符号名地址偏移相与的结果,通过这个word,就可以找到函数名了

但是我们的调用栈拿到的是pc指针,根本不知道在自己在什么函数里,因此可以通过从pc指针出发,向上扫描0xff000000这个魔鬼数字,进而拿到函数字符串的地址

thumb模式

另外,需要去掉-mthumb选项。在thumb模式下,fp指针也可以获取,不过和arm32位模式的寄存器不一样,arm32的fp是r11,thumb模式是r7,thumb和arm32可能会来回切换,因此在实现调用栈的时候,将要时时刻刻知道调用函数所在的cpu状态,在栈帧中也没有保存cpsr寄存器,故目前没有方法实现thumb模式的调用栈打印

rtems上的实现

rtems异常机制

rtems_fatal
RTEMS_NO_RETURN RTEMS_INLINE_ROUTINE void rtems_fatal(
  rtems_fatal_source fatal_source,
  rtems_fatal_code   error_code
)

rtems在检测到出错的时候,将会调用rtems_fatal接口用来通知系统出错了,这个出错的位置可以在任何上下文,任务、中断、boot_card,异常处理函数等等,通过fatal_source来告知,error_code是一个uint32_t的值,具体含义由fatal_source来定义

fatal_source有如下值

typedef enum {
   
  /**
   * @brief Errors of the core system.
   *
   * @see Internal_errors_Core_list.
   */
  INTERNAL_ERROR_CORE = 0,

  /**
   * @brief Errors of the RTEMS API.
   */
  INTERNAL_ERROR_RTEMS_API = 1,

  /**
   * @brief Errors of the POSIX API.
   */
  INTERNAL_ERROR_POSIX_API = 2,

  /**
   * @brief Fatal source for the block device cache.
   *
   * @see rtems_bdbuf_fatal_code.
   */
  RTEMS_FATAL_SOURCE_BDBUF = 3,

  /**
   * @brief Fatal source for application specific errors.
   *
   * The fatal code is application specific.
   */
  RTEMS_FATAL_SOURCE_APPLICATION = 4,

  /**
   * @brief Fatal source of exit().
   *
   * The fatal code is the exit() status code.
   */
  RTEMS_FATAL_SOURCE_EXIT = 5,

  /**
   * @brief Fatal source for BSP errors.
   *
   * The fatal codes are defined in <bsp/fatal.h>.  Examples are interrupt and
   * exception initialization.
   *
   * @see bsp_fatal_code and bsp_fatal().
   */
  RTEMS_FATAL_SOURCE_BSP = 6,

  /**
   * @brief Fatal source of assert().
   *
   * The fatal code is the pointer value of the assert context.
   *
   * @see rtems_assert_context.
   */
  RTEMS_FATAL_SOURCE_ASSERT = 7,

  /**
   * @brief Fatal source of the stack checker.
   *
   * The fatal code is the object name of the executing task.
   */
  RTEMS_FATAL_SOURCE_STACK_CHECKER = 8,

  /**
   * @brief Fatal source of the exceptions.
   *
   * The fatal code is the pointer value of the exception frame pointer.
   *
   * @see rtems_exception_frame and rtems_exception_frame_print().
   */
  RTEMS_FATAL_SOURCE_EXCEPTION = 9,

  /**
   * @brief Fatal source of SMP domain.
   *
   * @see SMP_Fatal_code.
   */
  RTEMS_FATAL_SOURCE_SMP = 10,

  /**
   * @brief Fatal source of rtems_panic().
   *
   * @see rtem
   */
  RTEMS_FATAL_SOURCE_PANIC = 11,

  /**
   * @brief Fatal source for invalid C program heap frees via free().
   *
   * The fatal code is the bad pointer.
   */
  RTEMS_FATAL_SOURCE_INVALID_HEAP_FREE = 12,

  /**
   * @brief Fatal source for heap errors.
   *
   * The fatal code is the address to a heap error context (Heap_Error_context).
   */
  RTEMS_FATAL_SOURCE_HEAP = 13,

  /**
   * @brief The last available fatal source.
   *
   * This enum value ensures that the enum type needs at least 32-bits for
   * architectures with short enums.
   */
  RTEMS_FATAL_SOURCE_LAST = 0xffffffff
} Internal_errors_Source;

其中RTEMS_FATAL_SOURCE_APPLICATION是在任务上下文触发,这个可以确定,RTEMS_FATAL_SOURCE_EXCEPTION这个是在异常上下文触发,这个也可以确定,其他都是不确定的

User extensions

User extensions是rtems的一种插件机制,rtems事先在系统运行的关键位置埋了点,如果想在这些时间点实现一些功能,实现一个插件就可以了

插件原型如下

typedef struct {
   
  User_extensions_thread_create_extension  thread_create;
  User_extensions_thread_start_extension   thread_start;
  User_extensions_thread_restart
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值