2013/01/08(火)sigactionを触ってみる。
backtraceを取れるか確認する(PwerPC 32bitでのみ確認)
glibcに、backtrace()函数があって、便利だなぁ、と。自分で書かなくて良いんだねぇ。組み込みRTOSで触ってた何か、は、スタックを手動で追っていたわ~。
コレも自動化しすぎて、スタックと思ったアドレスが別空間だとSIGSEGVでおちるけどな…
/* * sigaction sample program for powerpc32 * You can add more informations in segv_handler(). * In this fucntion, you have pointer of stacks, regs, contexts... * If we can allow increase size of binary, we can continu using backtrace_symbols()/backtrace_symbols_fd(). * Please refer man-pages, info-pages and a lot of WEB-pages B) * * Author: 30/Aug./2012 YNK * NOTE: Don't use '=O2' because optimization makes no 'bl' instructions to call function. */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <execinfo.h> #include <linux/sysctl.h> #include <sys/ucontext.h> int (*func_ptr)() = (void *)0x1234567; int func1(); int func2(); void segv_handler(int n, siginfo_t *pSigInf, void *pContext); int main(int argc,char ** argv) { struct sigaction sa; memset(&sa,0,sizeof(struct sigaction)); sigemptyset(&sa.sa_mask); sa.sa_flags |= SA_SIGINFO ; sa.sa_sigaction = segv_handler; sigaction(SIGSEGV,&sa,NULL); func1(); return 0; } int func1() { func2(); return 0; } int func2() { *(int*)0xBAD2DEAD = 2; func_ptr(); return 0; } void segv_handler(int n, siginfo_t *pSigInf, void *pContext) { int cnt, i; void **arr = alloca(256 * sizeof(void *)); ucontext_t* pCon = (ucontext_t *)pContext; printf("*** segmentation fault! (No=%d)\n", n); printf(" An errno value: %d\n", pSigInf->si_errno ); printf(" Signal code : %d\n", pSigInf->si_code ); printf(" access address : %p\n", pSigInf->si_addr ); // struct defined in ptrace.h for(i=0;i<32;i++) { printf("GPRS%2d: 0x%08X\n", i, pCon->uc_mcontext.regs->gpr[i]); } printf("NIP=0x%08X MSR=0x%08X\n", pCon->uc_mcontext.regs->nip, pCon->uc_mcontext.regs->msr ); printf("\n\n *** backtrace address ***\n"); cnt = backtrace(arr, 256); for(i=0;i<cnt;i++) { printf("\t%3d: 0x%08X\n", i, arr[i]); } /* if included symbolx(compile with "-r dynamic") */ backtrace_symbols_fd(arr, cnt, 2); abort(); }