testsig.c 2.65 KB
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>
#include <sys/ucontext.h>

jmp_buf jmp_env;

void alarm_handler(int sig)
{
    printf("alarm signal=%d\n", sig);
    alarm(1);
}

#ifndef REG_EAX
#define REG_EAX EAX
#define REG_EBX EBX
#define REG_ECX ECX
#define REG_EDX EDX
#define REG_ESI ESI
#define REG_EDI EDI
#define REG_EBP EBP
#define REG_ESP ESP
#define REG_EIP EIP
#define REG_EFL EFL
#endif

void dump_regs(struct ucontext *uc)
{
    printf("EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
           "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
           "EFL=%08x EIP=%08x\n",
           uc->uc_mcontext.gregs[REG_EAX],
           uc->uc_mcontext.gregs[REG_EBX],
           uc->uc_mcontext.gregs[REG_ECX],
           uc->uc_mcontext.gregs[REG_EDX],
           uc->uc_mcontext.gregs[REG_ESI],
           uc->uc_mcontext.gregs[REG_EDI],
           uc->uc_mcontext.gregs[REG_EBP],
           uc->uc_mcontext.gregs[REG_ESP],
           uc->uc_mcontext.gregs[REG_EFL],
           uc->uc_mcontext.gregs[REG_EIP]);
}

void sig_handler(int sig, siginfo_t *info, void *puc)
{
    struct ucontext *uc = puc;

    printf("%s: si_signo=%d si_errno=%d si_code=%d si_addr=0x%08lx\n",
           strsignal(info->si_signo),
           info->si_signo, info->si_errno, info->si_code, 
           (unsigned long)info->si_addr);
    dump_regs(uc);
    longjmp(jmp_env, 1);
}

int v1;

int main(int argc, char **argv)
{
    struct sigaction act;
    int i;
    
    /* test division by zero reporting */
    if (setjmp(jmp_env) == 0) {
        act.sa_sigaction = sig_handler;
        sigemptyset(&act.sa_mask);
        act.sa_flags = SA_SIGINFO | SA_ONESHOT;
        sigaction(SIGFPE, &act, NULL);
        
        /* now divide by zero */
        v1 = 0;
        v1 = 2 / v1;
    }

    /* test illegal instruction reporting */
    if (setjmp(jmp_env) == 0) {
        act.sa_sigaction = sig_handler;
        sigemptyset(&act.sa_mask);
        act.sa_flags = SA_SIGINFO | SA_ONESHOT;
        sigaction(SIGILL, &act, NULL);
        
        /* now execute an invalid instruction */
        asm volatile("ud2");
    }
    
    /* test SEGV reporting */
    if (setjmp(jmp_env) == 0) {
        act.sa_sigaction = sig_handler;
        sigemptyset(&act.sa_mask);
        act.sa_flags = SA_SIGINFO | SA_ONESHOT;
        sigaction(SIGSEGV, &act, NULL);
        
        /* now store in an invalid address */
        *(char *)0x1234 = 1;
    }
    
    act.sa_handler = alarm_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGALRM, &act, NULL);
    alarm(1);
    for(i = 0;i < 2; i++) {
        sleep(1);
    }
    return 0;
}