Cygwin: add newgrp release notes
[newlib-cygwin.git] / winsup / cygwin / scripts / gendef
blob3b1f8b9dae399bf95c6889da3ed5d5fce7ea479d
1 #!/usr/bin/perl
3 # This file is part of Cygwin.
5 # This software is a copyrighted work licensed under the terms of the
6 # Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 # details.
9 use strict;
10 use integer;
11 use Getopt::Long;
13 sub cleanup(@);
15 my $cpu;
16 my $output_def;
17 GetOptions('cpu=s'=>\$cpu, 'output-def=s'=>\$output_def);
19 $main::first = 0;
20 if (!defined($cpu) || !defined($output_def)) {
21 die "$0: missing required option\n";
24 my $is_x86_64 = $cpu eq 'x86_64';
25 # FIXME? Do other (non-32 bit) arches on Windows still use symbol prefixes?
26 my $sym_prefix = '';
28 my @top = ();
29 while (<>) {
30 push(@top, cleanup $_);
31 last if /^\s*exports$/oi;
33 my @in = cleanup <>;
35 my %sigfe = ();
36 my @data = ();
37 my @nosigfuncs = ();
38 my @text = ();
39 for (@in) {
40 chomp;
41 s/\s+DATA$//o and do {
42 push @data, $_;
43 next;
45 if (/=/o) {
46 if (s/\s+NOSIGFE\s*$//) {
47 # nothing
48 } elsif (s/\s+SIGFE(_MAYBE)?$//) {
49 my $func = (split(' '))[2];
50 my $maybe = (defined($1) ? lc $1 : '') . '_';
51 $sigfe{$func} = '_sigfe' . $maybe . $func;
53 } else {
54 my ($func, $sigfe) = m%^\s*(\S+)(?:\s+((?:NO)?SIGFE(?:_MAYBE)?))?$%o;
55 if (defined($sigfe) && $sigfe =~ /^NO/o) {
56 $_ = $func;
57 } else {
58 $sigfe ||= 'sigfe';
59 $_ = '_' . lc($sigfe) . '_' . $func;
60 $sigfe{$func} = $_;
61 $_ = $func . ' = ' . $_;
64 s/(\S)\s+(\S)/$1 $2/go;
65 s/(\S)\s+$/$1/o;
66 s/^\s+(\S)/$1/o;
67 push @text, $_;
70 for (@text) {
71 my ($alias, $func) = /^(\S+)\s+=\s+(\S+)\s*$/o;
72 $_ = $alias . ' = ' . $sigfe{$func}
73 if defined($func) && $sigfe{$func};
76 open OUT, '>', $output_def or die "$0: couldn't open \"$output_def\" - $!\n";
77 push @top, (map {$_ . " DATA\n"} @data), (map {$_ . "\n"} @text);
78 print OUT @top;
79 close OUT;
81 open SIGFE, '>', 'sigfe.s' or die "$0: couldn't open 'sigfe.s' file for writing - $!\n";
83 for my $k (sort keys %sigfe) {
84 print SIGFE fefunc($k, $sigfe{$k});
86 close SIGFE;
88 sub fefunc {
89 my $func = $sym_prefix . shift;
90 my $fe = $sym_prefix . shift;
91 my $sigfe_func;
92 if ($is_x86_64) {
93 $sigfe_func = ($fe =~ /^(.*)_${func}$/)[0];
95 my $extra;
96 my $res;
97 if ($is_x86_64) {
98 $res = <<EOF;
99 .extern $func
100 .global $fe
101 .seh_proc $fe
102 $fe:
103 leaq $func(%rip),%r10
104 pushq %r10
105 .seh_pushreg %r10
106 .seh_endprologue
107 jmp $sigfe_func
108 .seh_endproc
112 if (!$main::first++) {
113 if ($is_x86_64) {
114 $res = <<EOF . longjmp () . $res;
115 .include "tlsoffsets"
116 .text
118 .seh_proc _sigfe_maybe
119 _sigfe_maybe: # stack is aligned on entry!
120 .seh_endprologue
121 movq %gs:8,%r10 # location of bottom of stack
122 leaq _cygtls.initialized(%r10),%r11 # where we will be looking
123 cmpq %r11,%rsp # stack loc > than tls
124 jge 0f # yep. we don't have a tls.
125 movl _cygtls.initialized(%r10),%r11d
126 cmpl \$0xc763173f,%r11d # initialized?
127 je 1f
128 0: ret
129 .seh_endproc
131 .seh_proc _sigfe
132 _sigfe: # stack is aligned on entry!
133 .seh_endprologue
134 movq %gs:8,%r10 # location of bottom of stack
135 1: movl \$1,%r11d # potential lock value
136 xchgl %r11d,_cygtls.stacklock(%r10) # see if we can grab it
137 movl %r11d,_cygtls.spinning(%r10) # flag if we are waiting for lock
138 testl %r11d,%r11d # it will be zero
139 jz 2f # if so
140 pause
141 jmp 1b # loop
142 2: movq \$8,%rax # have the lock, now increment the
143 xaddq %rax,_cygtls.stackptr(%r10) # stack pointer and get pointer
144 leaq _sigbe(%rip),%r11 # new place to return to
145 xchgq %r11,8(%rsp) # exchange with real return value
146 movq %r11,(%rax) # store real return value on alt stack
147 incl _cygtls.incyg(%r10)
148 decl _cygtls.stacklock(%r10) # remove lock
149 popq %rax # pop real function address from stack
150 jmp *%rax # and jmp to it
151 .seh_endproc
153 .global _sigbe
154 .seh_proc _sigbe
155 _sigbe: # return here after cygwin syscall
156 # stack is aligned on entry!
157 .seh_endprologue
158 movq %gs:8,%r10 # address of bottom of tls
159 1: movl \$1,%r11d # potential lock value
160 xchgl %r11d,_cygtls.stacklock(%r10) # see if we can grab it
161 movl %r11d,_cygtls.spinning(%r10) # flag if we are waiting for lock
162 testl %r11d,%r11d # it will be zero
163 jz 2f # if so
164 pause
165 jmp 1b # and loop
166 2: movq \$-8,%r11 # now decrement aux stack
167 xaddq %r11,_cygtls.stackptr(%r10) # and get pointer
168 movq -8(%r11),%r11 # get return address from signal stack
169 decl _cygtls.incyg(%r10)
170 decl _cygtls.stacklock(%r10) # release lock
171 jmp *%r11 # "return" to caller
172 .seh_endproc
174 .global sigdelayed
175 .seh_proc sigdelayed
176 sigdelayed:
177 pushq %r10 # used for return address injection
178 .seh_pushreg %r10
179 pushq %rbp
180 .seh_pushreg %rbp
181 movq %rsp,%rbp
182 pushf
183 .seh_pushreg %rax # fake, there's no .seh_pushreg for the flags
184 # stack is aligned or unaligned on entry!
185 # make sure it is aligned from here on
186 # We could be called from an interrupted thread which doesn't know
187 # about his fate, so save and restore everything and the kitchen sink.
188 andq \$0xfffffffffffffff0,%rsp
189 .seh_setframe %rbp,0
190 pushq %r15
191 .seh_pushreg %r15
192 pushq %r14
193 .seh_pushreg %r14
194 pushq %r13
195 .seh_pushreg %r13
196 pushq %r12
197 .seh_pushreg %r12
198 pushq %r11
199 .seh_pushreg %r11
200 pushq %r9
201 .seh_pushreg %r9
202 pushq %r8
203 .seh_pushreg %r8
204 pushq %rsi
205 .seh_pushreg %rsi
206 pushq %rdi
207 .seh_pushreg %rdi
208 pushq %rdx
209 .seh_pushreg %rdx
210 pushq %rcx
211 .seh_pushreg %rcx
212 pushq %rbx
213 .seh_pushreg %rbx
214 pushq %rax
215 .seh_pushreg %rax
216 subq \$0x128,%rsp
217 .seh_stackalloc 0x128
218 stmxcsr 0x124(%rsp)
219 fnstcw 0x120(%rsp)
220 movdqa %xmm15,0x110(%rsp)
221 movdqa %xmm14,0x100(%rsp)
222 movdqa %xmm13,0xf0(%rsp)
223 movdqa %xmm12,0xe0(%rsp)
224 movdqa %xmm11,0xd0(%rsp)
225 movdqa %xmm10,0xc0(%rsp)
226 movdqa %xmm9,0xb0(%rsp)
227 movdqa %xmm8,0xa0(%rsp)
228 movdqa %xmm7,0x90(%rsp)
229 movdqa %xmm6,0x80(%rsp)
230 movdqa %xmm5,0x70(%rsp)
231 movdqa %xmm4,0x60(%rsp)
232 movdqa %xmm3,0x50(%rsp)
233 movdqa %xmm2,0x40(%rsp)
234 movdqa %xmm1,0x30(%rsp)
235 movdqa %xmm0,0x20(%rsp)
236 .seh_endprologue
238 movq %gs:8,%r12 # get tls
239 movl _cygtls.saved_errno(%r12),%r15d # temporarily save saved_errno
240 movq \$_cygtls.start_offset,%rcx # point to beginning of tls block
241 addq %r12,%rcx # and store as first arg to method
242 call _ZN7_cygtls19call_signal_handlerEv # call handler
244 1: movl \$1,%r11d # potential lock value
245 xchgl %r11d,_cygtls.stacklock(%r12) # see if we can grab it
246 movl %r11d,_cygtls.spinning(%r12) # flag if we are waiting for lock
247 testl %r11d,%r11d # it will be zero
248 jz 2f # if so
249 pause
250 jmp 1b # and loop
251 2: testl %r15d,%r15d # was saved_errno < 0
252 jl 3f # yup. ignore it
253 movq _cygtls.errno_addr(%r12),%r11
254 movl %r15d,(%r11)
255 3: movq \$-8,%r11 # now decrement aux stack
256 xaddq %r11,_cygtls.stackptr(%r12) # and get pointer
257 xorq %r10,%r10
258 xchgq %r10,-8(%r11) # get return address from signal stack
259 xorl %r11d,%r11d
260 movl %r11d,_cygtls.incyg(%r12)
261 movl %r11d,_cygtls.stacklock(%r12) # unlock
262 movdqa 0x20(%rsp),%xmm0
263 movdqa 0x30(%rsp),%xmm1
264 movdqa 0x40(%rsp),%xmm2
265 movdqa 0x50(%rsp),%xmm3
266 movdqa 0x60(%rsp),%xmm4
267 movdqa 0x70(%rsp),%xmm5
268 movdqa 0x80(%rsp),%xmm6
269 movdqa 0x90(%rsp),%xmm7
270 movdqa 0xa0(%rsp),%xmm8
271 movdqa 0xb0(%rsp),%xmm9
272 movdqa 0xc0(%rsp),%xmm10
273 movdqa 0xd0(%rsp),%xmm11
274 movdqa 0xe0(%rsp),%xmm12
275 movdqa 0xf0(%rsp),%xmm13
276 movdqa 0x100(%rsp),%xmm14
277 movdqa 0x110(%rsp),%xmm15
278 fninit
279 fldcw 0x120(%rsp)
280 ldmxcsr 0x124(%rsp)
281 addq \$0x128,%rsp
282 popq %rax
283 popq %rbx
284 popq %rcx
285 popq %rdx
286 popq %rdi
287 popq %rsi
288 popq %r8
289 popq %r9
290 popq %r11
291 popq %r12
292 popq %r13
293 popq %r14
294 popq %r15
295 movq %rbp,%rsp
296 subq \$8, %rsp
297 popf
298 popq %rbp
299 xchgq %r10,(%rsp)
301 .seh_endproc
302 _sigdelayed_end:
303 .global _sigdelayed_end
305 # _cygtls::pop
306 .global _ZN7_cygtls3popEv
307 .seh_proc _ZN7_cygtls3popEv
308 _ZN7_cygtls3popEv:
309 .seh_endprologue
310 movq \$-8,%r11
311 xaddq %r11,_cygtls.stackptr_p(%rcx)
312 movq -8(%r11),%rax
314 .seh_endproc
316 # _cygtls::lock
317 .global _ZN7_cygtls4lockEv
318 .seh_proc _ZN7_cygtls4lockEv
319 _ZN7_cygtls4lockEv:
320 pushq %r12
321 .seh_pushreg %r12
322 .seh_endprologue
323 movq %rcx,%r12
324 1: movl \$1,%r11d
325 xchgl %r11d,_cygtls.stacklock_p(%r12)
326 testl %r11d,%r11d
327 jz 2f
328 pause
329 jmp 1b
330 2: popq %r12
332 .seh_endproc
334 # _cygtls::unlock
335 .global _ZN7_cygtls6unlockEv
336 .seh_proc _ZN7_cygtls6unlockEv
337 _ZN7_cygtls6unlockEv:
338 .seh_endprologue
339 decl _cygtls.stacklock_p(%rcx)
341 .seh_endproc
343 # _cygtls::locked
344 .global _ZN7_cygtls6lockedEv
345 .seh_proc _ZN7_cygtls6lockedEv
346 _ZN7_cygtls6lockedEv:
347 .seh_endprologue
348 movl _cygtls.stacklock_p(%rcx),%eax
350 .seh_endproc
352 .seh_proc stabilize_sig_stack
353 stabilize_sig_stack:
354 pushq %r12
355 .seh_pushreg %r12
356 subq \$0x20,%rsp
357 .seh_stackalloc 32
358 .seh_endprologue
359 movq %gs:8,%r12
360 1: movl \$1,%r10d
361 xchgl %r10d,_cygtls.stacklock(%r12)
362 movl %r10d,_cygtls.spinning(%r12) # flag if we are waiting for lock
363 testl %r10d,%r10d
364 jz 2f
365 pause
366 jmp 1b
367 2: incl _cygtls.incyg(%r12)
368 cmpl \$0,_cygtls.sig(%r12)
369 jz 3f
370 decl _cygtls.stacklock(%r12) # unlock
371 movq \$_cygtls.start_offset,%rcx # point to beginning
372 addq %r12,%rcx # of tls block
373 call _ZN7_cygtls19call_signal_handlerEv
374 jmp 1b
375 3: decl _cygtls.incyg(%r12)
376 addq \$0x20,%rsp
377 movq %r12,%r11 # return tls addr in r11
378 popq %r12
380 .seh_endproc
384 return $res;
387 sub longjmp {
388 if ($is_x86_64) {
389 return <<EOF;
391 .globl sigsetjmp
392 .seh_proc sigsetjmp
393 sigsetjmp:
394 .seh_endprologue
395 movl %edx,0x100(%rcx) # store savemask
396 testl %edx,%edx # savemask != 0?
397 je setjmp # no, skip fetching sigmask
398 pushq %rcx
399 subq \$0x20,%rsp
400 leaq 0x108(%rcx),%r8 # &sigjmp_buf.sigmask
401 xorq %rdx,%rdx # NULL
402 xorl %ecx,%ecx # SIG_SETMASK
403 call pthread_sigmask
404 addq \$0x20,%rsp
405 popq %rcx
406 jmp setjmp
407 .seh_endproc
409 .globl setjmp
410 .seh_proc setjmp
411 setjmp:
412 .seh_endprologue
413 # We use the Windows jmp_buf layout with two small twists.
414 # - we store the tls stackptr in Frame, MSVCRT stores a second copy
415 # of %rbp in Frame (twice? why?)
416 # - we just store %rsp as is, MSVCRT stores %rsp of the caller in Rsp
417 movq %rbx,0x8(%rcx)
418 movq %rsp,0x10(%rcx)
419 movq %rbp,0x18(%rcx)
420 movq %rsi,0x20(%rcx)
421 movq %rdi,0x28(%rcx)
422 movq %r12,0x30(%rcx)
423 movq %r13,0x38(%rcx)
424 movq %r14,0x40(%rcx)
425 movq %r15,0x48(%rcx)
426 movq (%rsp),%r10
427 movq %r10,0x50(%rcx)
428 stmxcsr 0x58(%rcx)
429 fnstcw 0x5c(%rcx)
430 # jmp_buf is potentially unaligned!
431 movdqu %xmm6,0x60(%rcx)
432 movdqu %xmm7,0x70(%rcx)
433 movdqu %xmm8,0x80(%rcx)
434 movdqu %xmm9,0x90(%rcx)
435 movdqu %xmm10,0xa0(%rcx)
436 movdqu %xmm11,0xb0(%rcx)
437 movdqu %xmm12,0xc0(%rcx)
438 movdqu %xmm13,0xd0(%rcx)
439 movdqu %xmm14,0xe0(%rcx)
440 movdqu %xmm15,0xf0(%rcx)
441 pushq %rcx
442 .seh_pushreg %rcx
443 call stabilize_sig_stack # returns tls in r11
444 popq %rcx
445 movq _cygtls.stackptr(%r11),%r10
446 movq %r10,(%rcx)
447 decl _cygtls.stacklock(%r11)
448 xorl %eax,%eax
450 .seh_endproc
452 .globl siglongjmp
453 .seh_proc siglongjmp
454 siglongjmp:
455 pushq %rcx
456 .seh_pushreg %rcx
457 .seh_endprologue
458 movl %edx, %r12d
459 movl 0x100(%rcx),%r8d # savemask
460 testl %r8d,%r8d # savemask != 0?
461 je 1f # no, jmp to longjmp
462 xorq %r8,%r8 # NULL
463 leaq 0x108(%rcx),%rdx # &sigjmp_buf.sigmask
464 xorl %ecx,%ecx # SIG_SETMASK
465 subq \$0x20,%rsp
466 call pthread_sigmask
467 addq \$0x20,%rsp
468 jmp 1f
469 .seh_endproc
471 .globl longjmp
472 .seh_proc longjmp
473 longjmp:
474 pushq %rcx
475 .seh_pushreg %rcx
476 .seh_endprologue
477 movl %edx,%r12d # save return value
479 call stabilize_sig_stack # returns tls in r11
480 popq %rcx
481 movl %r12d,%eax # restore return value
482 movq (%rcx),%r10 # get old signal stack
483 movq %r10,_cygtls.stackptr(%r11) # restore
484 decl _cygtls.stacklock(%r11) # relinquish lock
485 xorl %r10d,%r10d
486 movl %r10d,_cygtls.incyg(%r11) # we're not in cygwin anymore
487 movq 0x8(%rcx),%rbx
488 movq 0x10(%rcx),%rsp
489 movq 0x18(%rcx),%rbp
490 movq 0x20(%rcx),%rsi
491 movq 0x28(%rcx),%rdi
492 movq 0x30(%rcx),%r12
493 movq 0x38(%rcx),%r13
494 movq 0x40(%rcx),%r14
495 movq 0x48(%rcx),%r15
496 movq 0x50(%rcx),%r10
497 movq %r10,(%rsp)
498 ldmxcsr 0x58(%rcx)
499 fnclex
500 fldcw 0x5c(%rcx)
501 # jmp_buf is potentially unaligned!
502 movdqu 0x60(%rcx),%xmm6
503 movdqu 0x70(%rcx),%xmm7
504 movdqu 0x80(%rcx),%xmm8
505 movdqu 0x90(%rcx),%xmm9
506 movdqu 0xa0(%rcx),%xmm10
507 movdqu 0xb0(%rcx),%xmm11
508 movdqu 0xc0(%rcx),%xmm12
509 movdqu 0xd0(%rcx),%xmm13
510 movdqu 0xe0(%rcx),%xmm14
511 movdqu 0xf0(%rcx),%xmm15
512 testl %eax,%eax
513 jne 0f
514 incl %eax
515 0: ret
516 .seh_endproc
521 sub cleanup(@) {
522 grep {s/\r//og; s/#.*//og; s/\s+\n//sog; !/^$/o && $_} @_;