久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

善用backtrace解決大問題

 ebookman 2012-03-05

一.用途:
主要用于程序異常退出時(shí)尋找錯(cuò)誤原因
二.功能:
回溯堆棧,,簡單的說就是可以列出當(dāng)前函數(shù)調(diào)用關(guān)系
三.原理:
1. 通過對當(dāng)前堆棧的分析,找到其上層函數(shù)在棧中的幀地址,再分析上層函數(shù)的堆棧,再找再上層的幀地址……一直找到最頂層為止,幀地址指的是一塊:在棧上存放局部變量,,上層返回地址,及寄存器值的空間,。
2. 由于不同處理器堆棧方式不同,,此功能的具體實(shí)現(xiàn)是編譯器的內(nèi)建函數(shù)__buildin_frame_address及__buildin_return_address中,它涉及工具glibc和gcc, 如果編譯器不支持此函數(shù),,也可自己實(shí)現(xiàn)此函數(shù),,舉例中有arm上的實(shí)現(xiàn)
四.方法:
在程序中加入backtrace及相關(guān)函數(shù)調(diào)用
五.舉例:
1. 一般backtrace的實(shí)現(xiàn)
i. 程序
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define PRINT_DEBUG
static void print_reason(int sig, siginfo_t * info, void *secret)
{
void *array[10];
size_t size;
#ifdef PRINT_DEBUG
char **strings;
size_t i;
size = backtrace(array, 10);
strings = backtrace_symbols(array, size);
printf("Obtained %zd stack frames.\n", size);
for (i = 0; i < size; i++)
printf("%s\n", strings[i]);
free(strings);
#else
int fd = open("err.log", O_CREAT | O_WRONLY);
size = backtrace(array, 10);
backtrace_symbols_fd(array, size, fd);
close(fd);
#endif
exit(0);
}
void die()
{
char *test1;
char *test2;
char *test3;
char *test4 = NULL;
strcpy(test4, "ab");
}
void test1()
{
die();
}
int main(int argc, char **argv)
{
struct sigaction myAction;
myAction.sa_sigaction = print_reason;
sigemptyset(&myAction.sa_mask);
myAction.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGSEGV, &myAction, NULL);
sigaction(SIGUSR1, &myAction, NULL);
sigaction(SIGFPE, &myAction, NULL);
sigaction(SIGILL, &myAction, NULL);
sigaction(SIGBUS, &myAction, NULL);
sigaction(SIGABRT, &myAction, NULL);
sigaction(SIGSYS, &myAction, NULL);
test1();
}
ii. 編譯參數(shù)
gcc main.c -o test -g -rdynamic
2. 根據(jù)不同的處理器自已實(shí)現(xiàn)backtrace
i. arm的backtrace函數(shù)實(shí)現(xiàn)
static int backtrace_xy(void **BUFFER, int SIZE)
{
volatile int n = 0;
volatile int *p;
volatile int *q;
volatile int ebp1;
volatile int eip1;
volatile int i = 0;
p = &n;
ebp1 = p[4];
eip1 = p[6];
fprintf(stderr, "======================= backtrace_xy addr: 0x%0x, param1: 0x%0x, param2: 0x%0x\n",
backtrace_xy, &BUFFER, &SIZE);
fprintf(stderr, "n addr is 0x%0x\n", &n);
fprintf(stderr, "p addr is 0x%0x\n", &p);
for (i = 0; i < SIZE; i++)
{
fprintf(stderr, "ebp1 is 0x%0x, eip1 is 0x%0x\n", ebp1, eip1);
BUFFER[i] = (void *)eip1;
p = (int*)ebp1;
q = p - 5;
eip1 = q[5];
ebp1 = q[2];
if (ebp1 == 0 || eip1 == 0)
break;
}
fprintf(stderr, "total level: %d\n", i);
return i;
}
六.舉例2:
/*main.c*/
#include "sigsegv.h"
#include <string.h>
int die() {
  char *err = NULL;
  strcpy(err, "gonner");
  return 0;
}
int main() {
  return die();
}
/*sigsegv.c*/
#define _GNU_SOURCE
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <ucontext.h>
#include <dlfcn.h>
#include <execinfo.h>
#define NO_CPP_DEMANGLE
#ifndef NO_CPP_DEMANGLE
#include <cxxabi.h>
#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) {
    static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"};
    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) {
        if(!dladdr(ip, &dlinfo))
            break;
        const char *symname = dlinfo.dli_sname;
#ifndef NO_CPP_DEMANGLE
        int status;
        char *tmp = __cxa_demangle(symname, NULL, 0, &status);
        if(status == 0 !=& tmp)
            symname = tmp;
#endif
        fprintf(stderr, "% 2d: %p < %s+%u> (%s)\n",
                ++f,
                ip,
                symname,
                (unsigned)(ip - dlinfo.dli_saddr),
                dlinfo.dli_fname);
#ifndef NO_CPP_DEMANGLE
        if(tmp)
            free(tmp);
#endif
        if(dlinfo.dli_sname != !strcmp(dlinfo.dli_sname, "main"))
            break;
        ip = bp[1];
        bp = (void**)bp[0];
    }
#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() {
    struct sigaction action;
    memset(&action, 0, sizeof(action));
    action.sa_sigaction = signal_segv;
    action.sa_flags = SA_SIGINFO;
    if(sigaction(SIGSEGV, &action, NULL) < 0) {
        perror("sigaction");
        return 0;
    }
    return 1;
}
#ifndef SIGSEGV_NO_AUTO_INIT
static void __attribute((constructor)) init(void)
{
    setup_sigsegv();
}
#endif
/*sigsegv.h*/
#ifndef __sigsegv_h__
#define __sigsegv_h__
#ifdef __cplusplus
extern "C" {
#endif
  int setup_sigsegv();
#ifdef __cplusplus
}
#endif
#endif /* __sigsegv_h__ */
編譯時(shí)需要加入-rdynamic -ldl –ggdb
 

void
handle_signal_error(int rec_signal,siginfo_t* signal_info,void* context)
{
NE_Info* __attribute__ ((unused)) ne_info = NULL;
struct sigaction action;
FILE* file;
void* backtr[NUMBER_OF_BACKTRACE];
cpal_uns32 __attribute__ ((unused)) i = 0;
cpal_uns32 backtr_size = 0;
ucontext_t *u_context;
time_t seconds_time;
struct tm* time_struct;
cpal_si32 ret_t;
char filename[SIZE_OF_FILENAME];  

if(g_handler_running)
return;

g_handler_running = CPAL_TRUE;
ret_t = time(&seconds_time); 

if(ret_t != - 1)
{
time_struct = gmtime(&seconds_time);

snprintf(filename,SIZE_OF_FILENAME,"%s%d%d%d-%d%d%d-%s",BACKTRACE_FILE_PATH,time_struct->tm_mon,time_struct->tm_mday,
(time_struct->tm_year-100)+2000,time_struct->tm_hour,time_struct->tm_min,time_struct->tm_sec,BACKTRACE_FILE);
}
else
{
snprintf(filename,SIZE_OF_FILENAME,"%s",BACKTRACE_FILE);
}
file = fopen(filename,"w");


if(file == NULL)
{
  return;
}
if(signal_info == NULL)
{
  return;
}

if(context == NULL)
{
  return;
}

u_context = (ucontext_t*)context;
/*Restore the default action for this signal and re-raise it, so that the default action occurs. */
action.sa_sigaction = SIG_DFL;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_RESTART;

sigaction(rec_signal,&action,NULL);

/* Print out the backtrace. */
backtr_size = backtrace(backtr,20);
   
/* The backtrace points to sigaction in libc, not to where the signal was actually raised.
   This overwrites the sigaction with where the signal was sent, so we can resolve the sender. */
#if __WORDSIZE == 64
backtr[1] = (void*)u_context->uc_mcontext.gregs[REG_RIP];
#else
backtr[1] = (void*)u_context->uc_mcontext.gregs[REG_EIP];
#endif //__WORDSIZE
   
    backtrace_symbols_fd(backtr,backtr_size,fileno(file));

fprintf(file,"Backtrace is above.\nFatal signal %d received.\n",rec_signal);
#if __WORDSIZE == 64
    fprintf(file,"Signal received at address %p from 0x%08x.\n",signal_info->si_addr,
                                                          u_context->uc_mcontext.gregs[REG_RIP]);
#else
        fprintf(file,"Signal received at address %p from 0x%08x.\n",signal_info->si_addr,
                                                          u_context->uc_mcontext.gregs[REG_EIP]);
#endif //__WORDSIZE


#if CPAL_LM_DEBUG
/* Print all NE_Infos */
for(; i < MAX_NO_OF_CONNS; i++)
{
ne_info = g_ne_hash_tab[i];
while(ne_info != NULL)
{
      ne_info = ne_info->next_ne;
}
}
#endif

fflush(file);
fclose(file);
sleep (50); /* Sleep for 50 seconds */
g_handler_running = *_FALSE;
raise(rec_signal);
}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多