织梦CMS - 轻松建站从此开始!

罗索实验室

当前位置: 主页 > 基础技术 > Linux开发专题 >

arm uclibc中实现backtrace

jackyhwei 发布于 2016-12-07 11:27 点击:次 
在arm中很多平台并无法使用gclibc环境,无法使用gclibc给出的backtrace,在这种情况下如果应用程序出错,出现段错误等情况,无法准确的定位出段错误的根源,经过研究之后终于折腾出了适用于ucl
TAG: backtrace  dumpstack  

在arm中很多平台并无法使用gclibc环境,无法使用gclibc给出的backtrace,在这种情况下如果应用程序出错,出现段错误等情况,无法准确的定位出段错误的根源,经过研究之后终于折腾出了适用于uclibc环境中的dumpstack方法

 

#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ucontext.h>
#include <signal.h>
#include <dlfcn.h>

 

typedef struct
{
    const char *dli_fname;  /* File name of defining object.  */
    void *dli_fbase;        /* Load address of that object.  */
    const char *dli_sname;  /* Name of nearest symbol.比如函数名*/
    void *dli_saddr;        /* Exact value of nearest symbol.比如函数的起始地址*/
} Dl_info;


struct ucontext_ce123 {
    unsigned long     uc_flags;
    struct ucontext  *uc_link;
    stack_t       uc_stack;
    struct sigcontext uc_mcontext;
    sigset_t      uc_sigmask;   /* mask last for extensibility */
}ucontext_ce123_;


struct sigframe_ce123 {
    struct sigcontext sc;//保存一组寄存器上下文
    unsigned long extramask[1];
    unsigned long retcode;//保存返回地址
    //struct aux_sigframe aux __attribute__((aligned(8)));
}sigframe_ce123;


void dumpstack()
{


    Dl_info info;
    int status;


    int *fp = 0, *next_fp = 0;
    int cnt = 0;
    int ret = 0;


    __asm__(
        "mov %0, fp\n"
        : "=r"(fp)
    );




    next_fp = (int *)(*(fp-3));
    while(next_fp != 0)
    {
        void * pcur = (void *)*(next_fp - 1);


        status = dladdr (pcur, &info);
        if (status && info.dli_fname && info.dli_fname[0] != '\0')
        {
            printf("0x%08x 0x%08x %-20s <  %s+%p  >\r\n",pcur,info.dli_saddr,info.dli_fname,info.dli_sname,(unsigned long)((unsigned int)pcur - (unsigned int)info.dli_saddr));
        }
        else
         {
            printf ( "[%p]", (void *)*(next_fp - 1));
         }


        //array[cnt++] = (void *)*(next_fp - 1);
        next_fp = (int *)(*(next_fp-3));
        cnt++;
    }

    printf("Backstrace (%d deep)\n", cnt);
}

 

在arm-linux-gcc编译需要加入参数-ldl -rdynamic使得编译通过

 

使用方法:

static void my_sighdlr (int sig)
{
if (sig == SIGSEGV)
        { // Ignore SIGPIPE.
   dumpstack();
                return;
        }
go = 0;
}

int testfun(int n)

{

dumpstack();

if(n>=10)

{

memset(0,0,100);

}

testfun(n++);

}
int main()
{
signal(SIGSEGV, my_sighdlr);

testfun(0);

return 0;
}

(dragon101788)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www1.rosoo.net/a/201612/17481.html]
本文出处:CSDN博客 作者:dragon101788
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容