aboutsummaryrefslogtreecommitdiff
path: root/tests/tcg/i386/test-flags.c
blob: c379e296275ef91980bedd657c08a3694be4bd1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#define _GNU_SOURCE
#include <sys/mman.h>
#include <signal.h>
#include <stdio.h>
#include <assert.h>

volatile unsigned long flags;
volatile unsigned long flags_after;
int *addr;

void sigsegv(int sig, siginfo_t *info, ucontext_t *uc)
{
    flags = uc->uc_mcontext.gregs[REG_EFL];
    mprotect(addr, 4096, PROT_READ|PROT_WRITE);
}

int main()
{
    struct sigaction sa = { .sa_handler = (void *)sigsegv, .sa_flags = SA_SIGINFO };
    sigaction(SIGSEGV, &sa, NULL);

    /* fault in the page then protect it */
    addr = mmap (NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
    *addr = 0x1234;
    mprotect(addr, 4096, PROT_READ);

    asm("# set flags to all ones    \n"
        "mov $-1, %%eax             \n"
        "movq addr, %%rdi           \n"
        "sahf                       \n"
        "sub %%eax, (%%rdi)         \n"
        "pushf                      \n"
        "pop  flags_after(%%rip)    \n" : : : "eax", "edi", "memory");

    /* OF can have any value before the SUB instruction.  */
    assert((flags & 0xff) == 0xd7 && (flags_after & 0x8ff) == 0x17);
}