一.用途:
主要用於程式異常退出時尋找錯誤原因
二.功能:
回溯堆疊,簡單的說就是可以列出當前函式呼叫關係
三.原理: 1.
通過對當前堆疊的分析,找到其上層函式在棧中的幀位址,再分析上層函式的堆疊,再找再上層的幀位址
……一直找到最頂層為止,幀位址指的是一塊:在棧上存放區域性變數,上層返回位址,及暫存器值的空間。 2.
由於不同處理器堆疊方式不同,此功能的具體實現是編譯器的內建函式
__buildin_frame_address
及__buildin_return_address
中,它涉及工具
glibc
和gcc,
如果編譯器不支援此函式,也可自己實現此函式,舉例中有
arm上的實現 四.
方法:在程式中加入
backtrace
及相關函式呼叫 五.
舉例:
1.一般
backtrace
的實現
i.程式
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define print_debug
static void print_reason(int sig, siginfo_t * info, void *secret)
void die()
void test1()
int main(int argc, char **argv)
ii.編譯引數
gcc main.c -o test -g -rdynamic
2.根據不同的處理器自已實現
backtrace
i.arm
的backtrace
函式實現
static int backtrace_xy(void **buffer, int size)
fprintf(stderr, "total level: %d\n", i);
return i; }
六.舉例2:
/*main.c*/
#include "sigsegv.h"
#include
int die()
int main()
/*sigsegv.c*/
#define _gnu_source
#include
#include
#include
#include
#include
#include
#include
#define no_cpp_demangle
#ifndef no_cpp_demangle
#include
#endif
#if defined(reg_rip)
# define sigsegv_stack_ia64
# define regformat "%016lx"
#elif defined(reg_eip)
# define sigsegv_stack_x86
# define regformat "%08x"
#else
# define sigsegv_stack_generic
# define regformat "%x"
#endif
static void signal_segv(int signum, siginfo_t* info, void*ptr) ;
size_t i;
ucontext_t *ucontext = (ucontext_t*)ptr;
#if defined(sigsegv_stack_x86) || defined(sigsegv_stack_ia64)
int f = 0;
dl_info dlinfo;
void **bp = 0;
void *ip = 0;
#else
void *bt[20];
char **strings;
size_t sz;
#endif
fprintf(stderr, "segmentation fault!\n");
fprintf(stderr, "info->si_signo = %d\n", signum);
fprintf(stderr, "info->si_errno = %d\n", info->si_errno);
// fprintf(stderr, "info->si_code = %d (%s)\n", info->si_code, info->si_codes[si_code]);
fprintf(stderr, "info->si_addr = %p\n", info->si_addr);
for(i = 0; i < ngreg; i++)
fprintf(stderr, "reg[%02d] = 0x" regformat "\n", i, ucontext->uc_mcontext.gregs[i]);
#if defined(sigsegv_stack_x86) || defined(sigsegv_stack_ia64)
# if defined(sigsegv_stack_ia64)
ip = (void*)ucontext->uc_mcontext.gregs[reg_rip];
bp = (void**)ucontext->uc_mcontext.gregs[reg_rbp];
# elif defined(sigsegv_stack_x86)
ip = (void*)ucontext->uc_mcontext.gregs[reg_eip];
bp = (void**)ucontext->uc_mcontext.gregs[reg_ebp];
# endif
fprintf(stderr, "stack trace:\n");
while(bp != & ip)
#else
fprintf(stderr, "stack trace (non-dedicated):\n");
sz = backtrace(bt, 20);
strings = backtrace_symbols(bt, sz);
for(i = 0; i < sz; ++i)
fprintf(stderr, "%s\n", strings[i]);
#endif
fprintf(stderr, "end of stack trace\n");
exit (-1);
}int setup_sigsegv()
return 1;
}#ifndef sigsegv_no_auto_init
static void __attribute((constructor)) init(void)
#endif
/*sigsegv.h*/
#ifndef __sigsegv_h__
#define __sigsegv_h__
#ifdef __cplusplus
extern "c"
#endif
#endif /* __sigsegv_h__ */
編譯時需要加入-rdynamic -ldl -ggdb
解決ADB server didn t ACK問題
之前執行eclipse執行android應用都沒問題,今天突然出問題了,控制台報錯 the connection to adb is down,and a severe error has occured.you must restart adb and eclipse.please ensure ...
解決ADB server didn t ACK問題
之前執行eclipse執行android應用都沒問題,今天突然出問題了,控制台報錯 the connection to adb is down,and a severe error has occured.you must restart adb and eclipse.please ensure ...
解決ADB server didn t ACK問題
執行eclipse執行android應用,控制台報錯 the connection to adb is down,and a severe error has occured.you must restart adb and eclipse.please ensure that adb is cor...