在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) |