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();
}