1cbdddcfb32883a37e873907602d34bac523e3eadsewardj#define _GNU_SOURCE
2cbdddcfb32883a37e873907602d34bac523e3eadsewardj
3cbdddcfb32883a37e873907602d34bac523e3eadsewardj#include <stdio.h>
4cbdddcfb32883a37e873907602d34bac523e3eadsewardj#include <signal.h>
5cbdddcfb32883a37e873907602d34bac523e3eadsewardj#include <unistd.h>
6cbdddcfb32883a37e873907602d34bac523e3eadsewardj#include <sys/ucontext.h>
7cbdddcfb32883a37e873907602d34bac523e3eadsewardj#include <asm/unistd.h>
8cbdddcfb32883a37e873907602d34bac523e3eadsewardj
9cbdddcfb32883a37e873907602d34bac523e3eadsewardj#define VAL1 0x11223344
10cbdddcfb32883a37e873907602d34bac523e3eadsewardj#define VAL2 0x44332211
11cbdddcfb32883a37e873907602d34bac523e3eadsewardj
12cbdddcfb32883a37e873907602d34bac523e3eadsewardjstatic void handler1(int sig, siginfo_t *si, ucontext_t *uc)
13cbdddcfb32883a37e873907602d34bac523e3eadsewardj{
14cbdddcfb32883a37e873907602d34bac523e3eadsewardj	/* Since the handler will be called as kill leaves the kernel,
15cbdddcfb32883a37e873907602d34bac523e3eadsewardj	   this is replacing the kill syscall's return value. */
16cbdddcfb32883a37e873907602d34bac523e3eadsewardj	if (uc->uc_mcontext.gregs[REG_EAX] != 0)
17cbdddcfb32883a37e873907602d34bac523e3eadsewardj		printf("FAILED: handler2 expected eax == 0, not %d\n", uc->uc_mcontext.gregs[REG_EAX]);
18cbdddcfb32883a37e873907602d34bac523e3eadsewardj	uc->uc_mcontext.gregs[REG_EAX] = VAL1;
19cbdddcfb32883a37e873907602d34bac523e3eadsewardj
20cbdddcfb32883a37e873907602d34bac523e3eadsewardj	asm volatile (
21cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0, %%edx\n"
22cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0, %%esi\n"
23cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0, %%edi\n"
24cbdddcfb32883a37e873907602d34bac523e3eadsewardj		: : : "edx", "esi", "edi");
25cbdddcfb32883a37e873907602d34bac523e3eadsewardj}
26cbdddcfb32883a37e873907602d34bac523e3eadsewardj
27cbdddcfb32883a37e873907602d34bac523e3eadsewardjstatic void handler2(int sig, struct sigcontext sc)
28cbdddcfb32883a37e873907602d34bac523e3eadsewardj{
29cbdddcfb32883a37e873907602d34bac523e3eadsewardj	/* Since the handler will be called as kill leaves the kernel,
30cbdddcfb32883a37e873907602d34bac523e3eadsewardj	   this is replacing the kill syscall's return value. */
31cbdddcfb32883a37e873907602d34bac523e3eadsewardj	if (sc.eax != 0)
3205c54a7bd19c7e2d847e686848d185a4a16fa465njn		printf("FAILED: handler2 expected eax == 0, not %p\n", (void*)sc.eax);
33cbdddcfb32883a37e873907602d34bac523e3eadsewardj
34cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sc.eax = VAL2;
35cbdddcfb32883a37e873907602d34bac523e3eadsewardj
36cbdddcfb32883a37e873907602d34bac523e3eadsewardj	asm volatile (
37cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0, %%edx\n"
38cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0, %%esi\n"
39cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0, %%edi\n"
40cbdddcfb32883a37e873907602d34bac523e3eadsewardj		: : : "edx", "esi", "edi");
41cbdddcfb32883a37e873907602d34bac523e3eadsewardj}
42cbdddcfb32883a37e873907602d34bac523e3eadsewardj
43cbdddcfb32883a37e873907602d34bac523e3eadsewardjint main()
44cbdddcfb32883a37e873907602d34bac523e3eadsewardj{
45cbdddcfb32883a37e873907602d34bac523e3eadsewardj	struct sigaction sa;
46cbdddcfb32883a37e873907602d34bac523e3eadsewardj	int ret;
4705c54a7bd19c7e2d847e686848d185a4a16fa465njn	int v2, v3, v4;
48cbdddcfb32883a37e873907602d34bac523e3eadsewardj
493d8525df0fc2c865ed589029e74a96e8f47d5f14njn	sa.sa_handler = (void*)handler1;
50cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sa.sa_flags = SA_SIGINFO;
51cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigfillset(&sa.sa_mask);
52cbdddcfb32883a37e873907602d34bac523e3eadsewardj
53cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigaction(SIGUSR1, &sa, NULL);
54cbdddcfb32883a37e873907602d34bac523e3eadsewardj
553d8525df0fc2c865ed589029e74a96e8f47d5f14njn	sa.sa_handler = (void*)handler2;
56cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sa.sa_flags = 0;
57cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigfillset(&sa.sa_mask);
58cbdddcfb32883a37e873907602d34bac523e3eadsewardj
59cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigaction(SIGUSR2, &sa, NULL);
60cbdddcfb32883a37e873907602d34bac523e3eadsewardj
61cbdddcfb32883a37e873907602d34bac523e3eadsewardj	asm volatile (
62cbdddcfb32883a37e873907602d34bac523e3eadsewardj		//"movl	$0x11111111, %%ebp\n"
63cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0x22222222, %%edx\n"
64cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0x33333333, %%esi\n"
65cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0x44444444, %%edi\n"
66cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"int $0x80"
67cbdddcfb32883a37e873907602d34bac523e3eadsewardj		: "=a" (ret),  "=d" (v2), "=S" (v3), "=D" (v4)
68cbdddcfb32883a37e873907602d34bac523e3eadsewardj		: "0" (__NR_kill), "b" (getpid()), "c" (SIGUSR1));
69cbdddcfb32883a37e873907602d34bac523e3eadsewardj	printf("v2=%x v3=%x v4=%x\n", v2, v3, v4);
70cbdddcfb32883a37e873907602d34bac523e3eadsewardj
71cbdddcfb32883a37e873907602d34bac523e3eadsewardj	if (ret == VAL1)
72cbdddcfb32883a37e873907602d34bac523e3eadsewardj		printf("PASS %x\n", ret);
73cbdddcfb32883a37e873907602d34bac523e3eadsewardj	else
74cbdddcfb32883a37e873907602d34bac523e3eadsewardj		printf("FAIL ret=%x not %x\n", ret, VAL1);
75cbdddcfb32883a37e873907602d34bac523e3eadsewardj
76cbdddcfb32883a37e873907602d34bac523e3eadsewardj	asm volatile (
77cbdddcfb32883a37e873907602d34bac523e3eadsewardj		//"movl	$0x11111111, %%ebp\n"
78cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0x22222222, %%edx\n"
79cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0x33333333, %%esi\n"
80cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"movl	$0x44444444, %%edi\n"
81cbdddcfb32883a37e873907602d34bac523e3eadsewardj		"int $0x80"
82cbdddcfb32883a37e873907602d34bac523e3eadsewardj		: "=a" (ret),  "=d" (v2), "=S" (v3), "=D" (v4)
83cbdddcfb32883a37e873907602d34bac523e3eadsewardj		: "0" (__NR_kill), "b" (getpid()), "c" (SIGUSR2));
84cbdddcfb32883a37e873907602d34bac523e3eadsewardj	printf("v2=%x v3=%x v4=%x\n", v2, v3, v4);
85cbdddcfb32883a37e873907602d34bac523e3eadsewardj
86cbdddcfb32883a37e873907602d34bac523e3eadsewardj	if (ret == VAL2)
87cbdddcfb32883a37e873907602d34bac523e3eadsewardj		printf("PASS %x\n", ret);
88cbdddcfb32883a37e873907602d34bac523e3eadsewardj	else
89cbdddcfb32883a37e873907602d34bac523e3eadsewardj		printf("FAIL ret=%x not %x\n", ret, VAL2);
90cbdddcfb32883a37e873907602d34bac523e3eadsewardj
91cbdddcfb32883a37e873907602d34bac523e3eadsewardj	return 0;
92cbdddcfb32883a37e873907602d34bac523e3eadsewardj}
93