善用backtrace解決大問題

2021-06-20 07:24:39 字數 3764 閱讀 6107

一.用途:

主要用於程式異常退出時尋找錯誤原因

二.功能:

回溯堆疊,簡單的說就是可以列出當前函式呼叫關係

三.原理: 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...