ELF文件——栈回溯

前言

本文以libunwind库对栈回溯流程进行描述。

libunwind栈回溯流程

libunwind包含两套使用接口,分别以前缀unw_和_Unwind标识,其中_Unwind前缀的接口是供C++异常处理的高级函数接口,unw前缀的则是更为底层通用的接口。根据libunwind代码中的configure.ac文件,在arm架构下是不使能C++的异常处理的,所以栈回溯使用的接口均为前缀位unw的函数接口。

AC_MSG_CHECKING([whether to enable C++ exception support])
AC_ARG_ENABLE(cxx_exceptions,
AS_HELP_STRING([--enable-cxx-exceptions],[use libunwind to handle C++ exceptions]),,
[
# C++ exception handling doesn't work too well on x86
case $target_arch in
  x86*) enable_cxx_exceptions=no;;
  aarch64*) enable_cxx_exceptions=no;;
  arm*) enable_cxx_exceptions=no;;
  mips*) enable_cxx_exceptions=no;;
  tile*) enable_cxx_exceptions=no;;
  *) enable_cxx_exceptions=yes;;
esac
])

栈回溯以函数unw_backtrace为起点:

int
unw_backtrace (void **buffer, int size)
{
   
  unw_cursor_t cursor;
  unw_context_t uc;
  int n = size;

  tdep_getcontext_trace (&uc); //保存当前寄存器的值

  if (unlikely (unw_init_local (&cursor, &uc) < 0))  //初始化cursor,保存当前寄存器的值
    return 0;

  if (unlikely (tdep_trace (&cursor, buffer, &n) < 0)) //快速查找,在cache中查找,如果在cache中没有找到,则需要根据elf文件逐个回溯
    {
   
      unw_getcontext (&uc);
      return slow_backtrace (buffer, size, &uc); //逐个函数进行回溯
    }

  return n;
}
libunwind_i.h
#define tdep_getcontext_trace           unw_getcontext
libunwind-common.h.in
#define unw_getcontext(uc)		unw_tdep_getcontext(uc)

libunwind-arm.h 
#ifndef __thumb__ 
#define unw_tdep_getcontext(uc) (({
                                          \ 
  unw_tdep_context_t *unw_ctx = (uc);                                   \ 
  register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs;      \ 
  __asm__ __volatile__ (                                                \ 
    "stmia %[base], {r0-r15}"                                           \ 
    : : [base] "r" (unw_base) : "memory");                              \ 
  }), 0) 
#else /* __thumb__ */ 
#define unw_tdep_getcontext(uc) (({
                                          \ 
  unw_tdep_context_t *unw_ctx = (uc);                                   \ 
  register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs;      \ 
  __asm__ __volatile__ (                                                \ 
    ".align 2\nbx pc\nnop\n.code 32\n"                                  \ 
    "stmia %[base], {r0-r15}\n"                                         \ 
    "orr %[base], pc, #1\nbx %[base]\n"                                 \ 
    ".code 16\n"                                                        \ 
    : [base] "+r" (unw_base) : : "memory", "cc");                       \ 
  }), 0) 
#endif
//将R0-R15的值依次保存到uc->reg[0] - uc->reg[15]中
int unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
{
   
  return unw_init_local_common(cursor, uc, 1
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值