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