Sunday, February 5, 2017

SIGSEGV second attempt

The previous SIGSEGV example didn't work on my Dragonboard when I compiled with:
gcc version 4.9.x 20150123 (prerelease) (GCC) 
Which is the gcc (with libs) that is included in the Android NDK R13b. The following was used for compiling:
aarch64-linux-android-gcc -Wall -g ${1}.c -o ${1}_arm64 -static
The problem is that siglongjmp() doesn't restore the sigprocmask. It's necessary to use "-static" for these binaries and the libc code in the NDK doesn't contain the call sigprocmask() which my Ubuntu libc does.

Reference: http://sourceware.org/git/?p=glibc.git;a=blob;f=setjmp/longjmp.c;h=2453c2c1249954eaceb43ebc02e7b77b02c96045;hb=HEAD


Thus the following is necessary to include:

static void sigsegvhandler(int sig, siginfo_t *siginfo, void *ptr) {
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGSEGV);
    sigprocmask(SIG_UNBLOCK, &set, NULL);
    siglongjmp(env, 1);
}

Wednesday, February 1, 2017

Linux SIGSEGV testing

A simple test for the signal handling in C and on Linux:

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <setjmp.h>

#define LOOP 5
static int* ptrs[LOOP];

static struct sigaction act;
static sigjmp_buf env;

static void sigsegvhandler(int sig, siginfo_t *siginfo, void *ptr) {
    siglongjmp(env, 1);
}

void func(int x) {
    printf("func(%d)...\n", x);
    if (sigsetjmp(env, 1) == 0) {
        *ptrs[x] = x;
        if (x == 4) {
            raise (SIGSEGV);
        }
    } else {
        printf("SIGSEGV recovery.\n");
    }
    printf("func(%d) done.\n", x);
}

int main(int argc, char *argv[]) {
    int x = 0;
    int a = 0;
    int b = 0;
    int c = 0;

    ptrs[0] = &a;
    ptrs[1] = NULL;
    ptrs[2] = &b;
    ptrs[3] = NULL;
    ptrs[4] = &c;

    printf("Hello SIGSEGV test!\n");
    printf("a=%d b=%d c=%d x=%d\n", a, b, c, x);

    memset(&act, 0, sizeof(act));
    act.sa_sigaction = sigsegvhandler;
    act.sa_flags = SA_SIGINFO;

    if (sigaction(SIGSEGV, &act, NULL)) {
        perror("sigaction");
        return 1;
    }

    while (x < 5) {
        printf("\nLoop x=%d...\n", x);
        func(x);
        x++;
    }

    printf("\na=%d b=%d c=%d x=%d\n", a, b, c, x);
    printf("Done.\n");
    return 0;
}
Output:
Hello SIGSEGV test!
a=0 b=0 c=0 x=0

Loop x=0...
func(0)...
func(0) done.

Loop x=1...
func(1)...
SIGSEGV recovery.
func(1) done.

Loop x=2...
func(2)...
func(2) done.

Loop x=3...
func(3)...
SIGSEGV recovery.
func(3) done.

Loop x=4...
func(4)...
SIGSEGV recovery.
func(4) done.

a=0 b=2 c=4 x=5
Done.

I keep forgetting...

I keep forgetting to put things on this blog. Working with too many things at the same time I guess.