#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
#include <pthread.h>
int main(void) {
    errno = 0;
    void *p = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
    printf("rw anon: %p errno=%d\n", p, errno);
    int r = mprotect(p, 4096, PROT_READ|PROT_EXEC);
    printf("mprotect rx: %d errno=%d %s\n", r, errno, strerror(errno));
    if (r == 0) {
        void *w = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
        unsigned int code[] = {0x52800540, 0xd65f03c0};
        memcpy(w, code, sizeof code);
        __builtin___clear_cache(w, (char*)w+sizeof code);
        mprotect(w, 4096, PROT_READ|PROT_EXEC);
        int (*f)(void) = (int(*)(void))w;
        printf("call mprotect rx -> %d\n", f());
    }
    errno = 0;
    void *j = mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON|MAP_JIT, -1, 0);
    printf("rwx MAP_JIT: %p errno=%d %s\n", j, errno, strerror(errno));
    if (j != MAP_FAILED) {
        pthread_jit_write_protect_np(0);
        unsigned int code[] = {0x52800540, 0xd65f03c0};
        memcpy(j, code, sizeof code);
        __builtin___clear_cache(j, (char*)j+sizeof code);
        pthread_jit_write_protect_np(1);
        int (*f)(void) = (int(*)(void))j;
        printf("call MAP_JIT -> %d\n", f());
    }
    return 0;
}
