summaryrefslogtreecommitdiff
path: root/winsup/cygwin/gendef
blob: 7e3a4aef996b22c02bdcb2e24809feb560f2ac15 (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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#!/usr/bin/perl
use strict;
my $in = shift;
my $tls_offsets = shift;
my $out = shift;
my $sigfe = shift;

$main::first = 0;
if (!defined($in) || !defined($out) || !defined($sigfe)) {
    die "usage: $0 deffile.in cygtls.h deffile.def sigfe.s\n";
}

require $tls_offsets;

open(IN, $in) or die "$0: couldn't open \"$in\" - $!\n";
my @top = ();
while (<IN>) {
    push(@top, $_);
    last if /^\s*exports\s*$/i;
}
my $libline = <IN>;
my @in = <IN>;
close(IN);

my %sigfe = ();
my @data = ();
my @nosigfuncs = ();
my @out = ();
for (@in) {
    /\sDATA$/o and do {
	push(@data, $_);
	next;
    };
    chomp;
    if (/=/o) {
	if (s/\s+NOSIGFE\s*$//) {
	} elsif (s/ SIGFE$//) {
	  my $func = (split(' '))[2];
	  $sigfe{$func} = '_sigfe_' . $func;
	}
    } else {
	my ($func, $sigfe) = m%^\s*(\S+)(?:\s+((?:NO)?SIGR?FE))?$%o;
	if (defined($sigfe) && $sigfe =~ /^NO/o) {
	    $_ = $func;
	} else {
	    $sigfe ||= 'sigfe';
	    $_ = '_' . lc($sigfe) . '_' . $func;
	    $sigfe{$func} = $_;
	    $_ = $func . ' = ' . $_;
	}
    }
    s/(\S)\s+(\S)/$1 $2/go;
    s/(\S)\s+$/$1/o;
    s/^\s+(\S)/$1/o;
    push(@out, $_ . "\n");
}

for (@out) {
    my ($alias, $func) = /^(\S+) = (\S+)\s*$/o;
    $_ = $alias . ' = ' . $sigfe{$func} . "\n"
      if defined($func) && $sigfe{$func};
}
open(OUT, '>', $out) or die "$0: couldn't open \"$out\" - $!\n";
print OUT @top, @data, @out;
close OUT;

open(SIGFE, '>', $sigfe) or die "$0: couldn't open sigfe file \"$sigfe\" - $!\n";

for my $k (sort keys %sigfe) {
    print SIGFE fefunc($k, $sigfe{$k});
}
close SIGFE;

sub fefunc {
    my $func = '_' . shift;
    my $fe = '_' . shift;
    my $extra;
    my $res = <<EOF;
	.extern	_siglist_index
	.extern	_siglist
	.extern	$func
	.global	$fe
$fe:
	pushl	\$$func
	jmp	__sigfe

EOF
    if (!$main::first++) {
	$res = <<EOF . longjmp () . $res;
	.text
	.global	__sigbe
	.global	_sigreturn
	.global	_sigdelayed

	.stabs	"_sigfe:F(0,1)",36,0,0,__sigbe
__sigfe:
	pushl	%edx
	movl	%fs:4,%eax
	movl	\$4,%edx
	xadd	%edx,$tls::stackptr(%eax)
	leal	__sigbe,%eax
	xchg	%eax,8(%esp)
	movl	%eax,(%edx)
	popl	%edx
	ret

	.stabs	"_sigbe:F(0,1)",36,0,0,__sigbe
__sigbe:
	pushl	%eax
	pushl	%edx
	movl	\$-4,%edx
1:	movl	%fs:4,%eax
	xadd	%edx,$tls::stackptr(%eax)
	xorl	%eax,%eax
	lock    xchg %eax,-4(%edx)
	testl	%eax,%eax
	jnz	2f
	call	_low_priority_sleep
	xorl	%edx,%edx
	jmp	1b
2:	xchg	%eax,4(%esp)
	popl	%edx
	ret

	.stabs	"sigreturn:F(0,1)",36,0,0,_sigreturn
_sigreturn:
	addl	\$4,%esp			# Remove argument
	call	_set_process_mask\@4

	movl	%fs:4,%ebx

	cmpl	\$0,$tls::sig(%ebx)	# Did a signal come in?
	jnz	3f			# Yes, if non-zero

1:	popl	%edx			# saved errno
	testl	%edx,%edx		# Is it < 0
	jl	2f			# yup.  ignore it
	movl	$tls::errno_addr(%ebx),%eax
	movl	%edx,(%eax)
2:	popl	%eax
	popl	%ebx
	popl	%ecx
	popl	%edx
	popl	%edi
	popl	%esi
	popf
	popl	%ebp
	jmp	__sigbe

	.stabs	"sigdelayed:F(0,1)",36,0,0,_sigdelayed
_sigdelayed:
	pushl	%ebp
	movl	%esp,%ebp
	pushf
	pushl	%esi
	pushl	%edi
	pushl	%edx
	pushl	%ecx
	pushl	%ebx
	pushl	%eax
	movl	%fs:4,%ebx
	pushl	$tls::saved_errno(%ebx)	# saved errno
3:	pushl	$tls::oldmask(%ebx)	# oldmask
	pushl	$tls::sig(%ebx)		# signal argument
	pushl	\$_sigreturn

	call	_reset_signal_arrived\@0
	pushl	$tls::func(%ebx)	# signal func
	pushl	$tls::newmask(%ebx)	# newmask - eaten by set_process_mask

	call	_set_process_mask\@4
	movl	\$0,$tls::sig(%ebx)	# zero the signal number as a
					# flag to the signal handler thread
					# that it is ok to set up sigsave
	popl	%ebx
	jmp	*%ebx

EOF
    }
    return $res;
}

sub longjmp {
    return <<EOF;

	.globl	_longjmp

_longjmp:
	pushl	%ebp
	movl	%esp,%ebp
	movl	8(%ebp),%edi
	movl	12(%ebp),%eax
	testl	%eax,%eax
	jne	0f
	incl	%eax
0:
	movl	%eax,0(%edi)
	movl	24(%edi),%ebp
	pushfl
	popl	%ebx
	movw	42(%edi),%ax
	movw	%ax,%ss
	movl	28(%edi),%esp
	pushl	32(%edi)
	pushl	%ebx
	movw	36(%edi),%ax
	movw	%ax,%es
	movw	40(%edi),%ax
	movw	%ax,%gs
	movl	%fs:4,%eax
	leal	($tls::stack)(%eax),%edx
	movl	%edx,($tls::stackptr)(%eax)
	movl	0(%edi),%eax
	movl	4(%edi),%ebx
	movl	8(%edi),%ecx
	movl	12(%edi),%edx
	movl	16(%edi),%esi
	movl	20(%edi),%edi
	popfl
	ret

EOF
}