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