1# x86/x86_64 support for -fsplit-stack. 2# Copyright (C) 2009-2022 Free Software Foundation, Inc. 3# Contributed by Ian Lance Taylor <iant@google.com>. 4 5# This file is part of GCC. 6 7# GCC is free software; you can redistribute it and/or modify it under 8# the terms of the GNU General Public License as published by the Free 9# Software Foundation; either version 3, or (at your option) any later 10# version. 11 12# GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13# WARRANTY; without even the implied warranty of MERCHANTABILITY or 14# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15# for more details. 16 17# Under Section 7 of GPL version 3, you are granted additional 18# permissions described in the GCC Runtime Library Exception, version 19# 3.1, as published by the Free Software Foundation. 20 21# You should have received a copy of the GNU General Public License and 22# a copy of the GCC Runtime Library Exception along with this program; 23# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24# <http://www.gnu.org/licenses/>. 25 26#include "auto-host.h" 27 28# Support for allocating more stack space when using -fsplit-stack. 29# When a function discovers that it needs more stack space, it will 30# call __morestack with the size of the stack frame and the size of 31# the parameters to copy from the old stack frame to the new one. 32# The __morestack function preserves the parameter registers and 33# calls __generic_morestack to actually allocate the stack space. 34 35# When this is called stack space is very low, but we ensure that 36# there is enough space to push the parameter registers and to call 37# __generic_morestack. 38 39# When calling __generic_morestack, FRAME_SIZE points to the size of 40# the desired frame when the function is called, and the function 41# sets it to the size of the allocated stack. OLD_STACK points to 42# the parameters on the old stack and PARAM_SIZE is the number of 43# bytes of parameters to copy to the new stack. These are the 44# parameters of the function that called __morestack. The 45# __generic_morestack function returns the new stack pointer, 46# pointing to the address of the first copied parameter. The return 47# value minus the returned *FRAME_SIZE will be the first address on 48# the stack which we should not use. 49 50# void *__generic_morestack (size_t *frame_size, void *old_stack, 51# size_t param_size); 52 53# The __morestack routine has to arrange for the caller to return to a 54# stub on the new stack. The stub is responsible for restoring the 55# old stack pointer and returning to the caller's caller. This calls 56# __generic_releasestack to retrieve the old stack pointer and release 57# the newly allocated stack. 58 59# void *__generic_releasestack (size_t *available); 60 61# We do a little dance so that the processor's call/return return 62# address prediction works out. The compiler arranges for the caller 63# to look like this: 64# call __generic_morestack 65# ret 66# L: 67# // carry on with function 68# After we allocate more stack, we call L, which is in our caller. 69# When that returns (to the predicted instruction), we release the 70# stack segment and reset the stack pointer. We then return to the 71# predicted instruction, namely the ret instruction immediately after 72# the call to __generic_morestack. That then returns to the caller of 73# the original caller. 74 75 76# The amount of extra space we ask for. In general this has to be 77# enough for the dynamic loader to find a symbol and for a signal 78# handler to run. 79 80#ifndef __x86_64__ 81#define BACKOFF (1024) 82#else 83#define BACKOFF (3584) 84#endif 85 86 87# The amount of space we ask for when calling non-split-stack code. 88#define NON_SPLIT_STACK 0x100000 89 90# This entry point is for split-stack code which calls non-split-stack 91# code. When the linker sees this case, it converts the call to 92# __morestack to call __morestack_non_split instead. We just bump the 93# requested stack space by 16K. 94 95#include <cet.h> 96 97 .global __morestack_non_split 98 .hidden __morestack_non_split 99 100#ifdef __ELF__ 101 .type __morestack_non_split,@function 102#endif 103 104__morestack_non_split: 105 .cfi_startproc 106 107#ifndef __x86_64__ 108 109 # See below for an extended explanation of this. 110 .cfi_def_cfa %esp,16 111 112 pushl %eax # Save %eax in case it is a parameter. 113 114 .cfi_adjust_cfa_offset 4 # Account for pushed register. 115 116 movl %esp,%eax # Current stack, 117 subl 8(%esp),%eax # less required stack frame size, 118 subl $NON_SPLIT_STACK,%eax # less space for non-split code. 119 cmpl %gs:0x30,%eax # See if we have enough space. 120 jb 2f # Get more space if we need it. 121 122 # Here the stack is 123 # %esp + 20: stack pointer after two returns 124 # %esp + 16: return address of morestack caller's caller 125 # %esp + 12: size of parameters 126 # %esp + 8: new stack frame size 127 # %esp + 4: return address of this function 128 # %esp: saved %eax 129 # 130 # Since we aren't doing a full split stack, we don't need to 131 # do anything when our caller returns. So we return to our 132 # caller rather than calling it, and let it return as usual. 133 # To make that work we adjust the return address. 134 135 # This breaks call/return address prediction for the call to 136 # this function. I can't figure out a way to make it work 137 # short of copying the parameters down the stack, which will 138 # probably take more clock cycles than we will lose breaking 139 # call/return address prediction. We will only break 140 # prediction for this call, not for our caller. 141 142 movl 4(%esp),%eax # Increment the return address 143 cmpb $0xc3,(%eax) # to skip the ret instruction; 144 je 1f # see above. 145 addl $2,%eax 1461: inc %eax 147 148 # If the instruction that we return to is 149 # leal 20(%ebp),{%eax,%ecx,%edx} 150 # then we have been called by a varargs function that expects 151 # %ebp to hold a real value. That can only work if we do the 152 # full stack split routine. FIXME: This is fragile. 153 cmpb $0x8d,(%eax) 154 jne 3f 155 cmpb $0x14,2(%eax) 156 jne 3f 157 cmpb $0x45,1(%eax) 158 je 2f 159 cmpb $0x4d,1(%eax) 160 je 2f 161 cmpb $0x55,1(%eax) 162 je 2f 163 1643: 165 movl %eax,4(%esp) # Update return address. 166 167 popl %eax # Restore %eax and stack. 168 169 .cfi_adjust_cfa_offset -4 # Account for popped register. 170 171 ret $8 # Return to caller, popping args. 172 1732: 174 .cfi_adjust_cfa_offset 4 # Back to where we were. 175 176 popl %eax # Restore %eax and stack. 177 178 .cfi_adjust_cfa_offset -4 # Account for popped register. 179 180 # Increment space we request. 181 addl $NON_SPLIT_STACK+0x1000+BACKOFF,4(%esp) 182 183 # Fall through into morestack. 184 185#else 186 187 # See below for an extended explanation of this. 188 .cfi_def_cfa %rsp,16 189 190 pushq %rax # Save %rax in case caller is using 191 # it to preserve original %r10. 192 .cfi_adjust_cfa_offset 8 # Adjust for pushed register. 193 194 movq %rsp,%rax # Current stack, 195 subq %r10,%rax # less required stack frame size, 196 subq $NON_SPLIT_STACK,%rax # less space for non-split code. 197 198#ifdef __LP64__ 199 cmpq %fs:0x70,%rax # See if we have enough space. 200#else 201 cmpl %fs:0x40,%eax 202#endif 203 204 jb 2f # Get more space if we need it. 205 206 # If the instruction that we return to is 207 # leaq 24(%rbp), %r11n 208 # then we have been called by a varargs function that expects 209 # %ebp to hold a real value. That can only work if we do the 210 # full stack split routine. FIXME: This is fragile. 211 movq 8(%rsp),%rax 212 incq %rax # Skip ret instruction in caller. 213 cmpl $0x185d8d4c,(%rax) 214 je 2f 215 216 # This breaks call/return prediction, as described above. 217 incq 8(%rsp) # Increment the return address. 218 219 popq %rax # Restore register. 220 221 .cfi_adjust_cfa_offset -8 # Adjust for popped register. 222 223 ret # Return to caller. 224 2252: 226 popq %rax # Restore register. 227 228 .cfi_adjust_cfa_offset -8 # Adjust for popped register. 229 230 # Increment space we request. 231 addq $NON_SPLIT_STACK+0x1000+BACKOFF,%r10 232 233 # Fall through into morestack. 234 235#endif 236 237 .cfi_endproc 238#ifdef __ELF__ 239 .size __morestack_non_split, . - __morestack_non_split 240#endif 241 242# __morestack_non_split falls through into __morestack. 243 244 245# The __morestack function. 246 247 .global __morestack 248 .hidden __morestack 249 250#ifdef __ELF__ 251 .type __morestack,@function 252#endif 253 254__morestack: 255.LFB1: 256 .cfi_startproc 257 258 259#ifndef __x86_64__ 260 261 262# The 32-bit __morestack function. 263 264 # We use a cleanup to restore the stack guard if an exception 265 # is thrown through this code. 266#ifndef __PIC__ 267 .cfi_personality 0,__gcc_personality_v0 268 .cfi_lsda 0,.LLSDA1 269#else 270 .cfi_personality 0x9b,DW.ref.__gcc_personality_v0 271 .cfi_lsda 0x1b,.LLSDA1 272#endif 273 274 # We return below with a ret $8. We will return to a single 275 # return instruction, which will return to the caller of our 276 # caller. We let the unwinder skip that single return 277 # instruction, and just return to the real caller. 278 279 # Here CFA points just past the return address on the stack, 280 # e.g., on function entry it is %esp + 4. The stack looks 281 # like this: 282 # CFA + 12: stack pointer after two returns 283 # CFA + 8: return address of morestack caller's caller 284 # CFA + 4: size of parameters 285 # CFA: new stack frame size 286 # CFA - 4: return address of this function 287 # CFA - 8: previous value of %ebp; %ebp points here 288 # Setting the new CFA to be the current CFA + 12 (i.e., %esp + 289 # 16) will make the unwinder pick up the right return address. 290 291 .cfi_def_cfa %esp,16 292 293 pushl %ebp 294 .cfi_adjust_cfa_offset 4 295 .cfi_offset %ebp, -20 296 movl %esp,%ebp 297 .cfi_def_cfa_register %ebp 298 299 # In 32-bit mode the parameters are pushed on the stack. The 300 # argument size is pushed then the new stack frame size is 301 # pushed. 302 303 # In the body of a non-leaf function, the stack pointer will 304 # be aligned to a 16-byte boundary. That is CFA + 12 in the 305 # stack picture above: (CFA + 12) % 16 == 0. At this point we 306 # have %esp == CFA - 8, so %esp % 16 == 12. We need some 307 # space for saving registers and passing parameters, and we 308 # need to wind up with %esp % 16 == 0. 309 subl $44,%esp 310 311 # Because our cleanup code may need to clobber %ebx, we need 312 # to save it here so the unwinder can restore the value used 313 # by the caller. Note that we don't have to restore the 314 # register, since we don't change it, we just have to save it 315 # for the unwinder. 316 movl %ebx,-4(%ebp) 317 .cfi_offset %ebx, -24 318 319 # In 32-bit mode the registers %eax, %edx, and %ecx may be 320 # used for parameters, depending on the regparm and fastcall 321 # attributes. 322 323 movl %eax,-8(%ebp) 324 movl %edx,-12(%ebp) 325 movl %ecx,-16(%ebp) 326 327 call __morestack_block_signals 328 329 movl 12(%ebp),%eax # The size of the parameters. 330 movl %eax,8(%esp) 331 leal 20(%ebp),%eax # Address of caller's parameters. 332 movl %eax,4(%esp) 333 addl $BACKOFF,8(%ebp) # Ask for backoff bytes. 334 leal 8(%ebp),%eax # The address of the new frame size. 335 movl %eax,(%esp) 336 337 call __generic_morestack 338 339 movl %eax,%esp # Switch to the new stack. 340 subl 8(%ebp),%eax # The end of the stack space. 341 addl $BACKOFF,%eax # Back off 512 bytes. 342 343.LEHB0: 344 # FIXME: The offset must match 345 # TARGET_THREAD_SPLIT_STACK_OFFSET in 346 # gcc/config/i386/linux.h. 347 movl %eax,%gs:0x30 # Save the new stack boundary. 348 349 call __morestack_unblock_signals 350 351 movl -12(%ebp),%edx # Restore registers. 352 movl -16(%ebp),%ecx 353 354 movl 4(%ebp),%eax # Increment the return address 355 cmpb $0xc3,(%eax) # to skip the ret instruction; 356 je 1f # see above. 357 addl $2,%eax 3581: inc %eax 359 360 movl %eax,-12(%ebp) # Store return address in an 361 # unused slot. 362 363 movl -8(%ebp),%eax # Restore the last register. 364 365 call *-12(%ebp) # Call our caller! 366 367 # The caller will return here, as predicted. 368 369 # Save the registers which may hold a return value. We 370 # assume that __generic_releasestack does not touch any 371 # floating point or vector registers. 372 pushl %eax 373 pushl %edx 374 375 # Push the arguments to __generic_releasestack now so that the 376 # stack is at a 16-byte boundary for 377 # __morestack_block_signals. 378 pushl $0 # Where the available space is returned. 379 leal 0(%esp),%eax # Push its address. 380 push %eax 381 382 call __morestack_block_signals 383 384 call __generic_releasestack 385 386 subl 4(%esp),%eax # Subtract available space. 387 addl $BACKOFF,%eax # Back off 512 bytes. 388.LEHE0: 389 movl %eax,%gs:0x30 # Save the new stack boundary. 390 391 addl $8,%esp # Remove values from stack. 392 393 # We need to restore the old stack pointer, which is in %rbp, 394 # before we unblock signals. We also need to restore %eax and 395 # %edx after we unblock signals but before we return. Do this 396 # by moving %eax and %edx from the current stack to the old 397 # stack. 398 399 popl %edx # Pop return value from current stack. 400 popl %eax 401 402 movl %ebp,%esp # Restore stack pointer. 403 404 # As before, we now have %esp % 16 == 12. 405 406 pushl %eax # Push return value on old stack. 407 pushl %edx 408 subl $4,%esp # Align stack to 16-byte boundary. 409 410 call __morestack_unblock_signals 411 412 addl $4,%esp 413 popl %edx # Restore return value. 414 popl %eax 415 416 .cfi_remember_state 417 418 # We never changed %ebx, so we don't have to actually restore it. 419 .cfi_restore %ebx 420 421 popl %ebp 422 .cfi_restore %ebp 423 .cfi_def_cfa %esp, 16 424 ret $8 # Return to caller, which will 425 # immediately return. Pop 426 # arguments as we go. 427 428# This is the cleanup code called by the stack unwinder when unwinding 429# through the code between .LEHB0 and .LEHE0 above. 430 431.L1: 432 .cfi_restore_state 433 subl $16,%esp # Maintain 16 byte alignment. 434 movl %eax,4(%esp) # Save exception header. 435 movl %ebp,(%esp) # Stack pointer after resume. 436 call __generic_findstack 437 movl %ebp,%ecx # Get the stack pointer. 438 subl %eax,%ecx # Subtract available space. 439 addl $BACKOFF,%ecx # Back off 512 bytes. 440 movl %ecx,%gs:0x30 # Save new stack boundary. 441 movl 4(%esp),%eax # Function argument. 442 movl %eax,(%esp) 443#ifdef __PIC__ 444 call __x86.get_pc_thunk.bx # %ebx may not be set up for us. 445 addl $_GLOBAL_OFFSET_TABLE_, %ebx 446 call _Unwind_Resume@PLT # Resume unwinding. 447#else 448 call _Unwind_Resume 449#endif 450 451#else /* defined(__x86_64__) */ 452 453 454# The 64-bit __morestack function. 455 456 # We use a cleanup to restore the stack guard if an exception 457 # is thrown through this code. 458#ifndef __PIC__ 459 .cfi_personality 0x3,__gcc_personality_v0 460 .cfi_lsda 0x3,.LLSDA1 461#else 462 .cfi_personality 0x9b,DW.ref.__gcc_personality_v0 463 .cfi_lsda 0x1b,.LLSDA1 464#endif 465 466 # We will return a single return instruction, which will 467 # return to the caller of our caller. Let the unwinder skip 468 # that single return instruction, and just return to the real 469 # caller. 470 .cfi_def_cfa %rsp,16 471 472 # Set up a normal backtrace. 473 pushq %rbp 474 .cfi_adjust_cfa_offset 8 475 .cfi_offset %rbp, -24 476 movq %rsp, %rbp 477 .cfi_def_cfa_register %rbp 478 479 # In 64-bit mode the new stack frame size is passed in r10 480 # and the argument size is passed in r11. 481 482 addq $BACKOFF,%r10 # Ask for backoff bytes. 483 pushq %r10 # Save new frame size. 484 485 # In 64-bit mode the registers %rdi, %rsi, %rdx, %rcx, %r8, 486 # and %r9 may be used for parameters. We also preserve %rax 487 # which the caller may use to hold %r10. 488 489 pushq %rax 490 pushq %rdi 491 pushq %rsi 492 pushq %rdx 493 pushq %rcx 494 pushq %r8 495 pushq %r9 496 497 pushq %r11 498 499 # We entered morestack with the stack pointer aligned to a 500 # 16-byte boundary (the call to morestack's caller used 8 501 # bytes, and the call to morestack used 8 bytes). We have now 502 # pushed 10 registers, so we are still aligned to a 16-byte 503 # boundary. 504 505 call __morestack_block_signals 506 507 leaq -8(%rbp),%rdi # Address of new frame size. 508 leaq 24(%rbp),%rsi # The caller's parameters. 509 popq %rdx # The size of the parameters. 510 511 subq $8,%rsp # Align stack. 512 513 call __generic_morestack 514 515 movq -8(%rbp),%r10 # Reload modified frame size 516 movq %rax,%rsp # Switch to the new stack. 517 subq %r10,%rax # The end of the stack space. 518 addq $BACKOFF,%rax # Back off 1024 bytes. 519 520.LEHB0: 521 # FIXME: The offset must match 522 # TARGET_THREAD_SPLIT_STACK_OFFSET in 523 # gcc/config/i386/linux64.h. 524 # Macro to save the new stack boundary. 525#ifdef __LP64__ 526#define X86_64_SAVE_NEW_STACK_BOUNDARY(reg) movq %r##reg,%fs:0x70 527#else 528#define X86_64_SAVE_NEW_STACK_BOUNDARY(reg) movl %e##reg,%fs:0x40 529#endif 530 X86_64_SAVE_NEW_STACK_BOUNDARY (ax) 531 532 call __morestack_unblock_signals 533 534 movq -24(%rbp),%rdi # Restore registers. 535 movq -32(%rbp),%rsi 536 movq -40(%rbp),%rdx 537 movq -48(%rbp),%rcx 538 movq -56(%rbp),%r8 539 movq -64(%rbp),%r9 540 541 movq 8(%rbp),%r10 # Increment the return address 542 incq %r10 # to skip the ret instruction; 543 # see above. 544 545 movq -16(%rbp),%rax # Restore caller's %rax. 546 547 call *%r10 # Call our caller! 548 549 # The caller will return here, as predicted. 550 551 # Save the registers which may hold a return value. We 552 # assume that __generic_releasestack does not touch any 553 # floating point or vector registers. 554 pushq %rax 555 pushq %rdx 556 557 call __morestack_block_signals 558 559 pushq $0 # For alignment. 560 pushq $0 # Where the available space is returned. 561 leaq 0(%rsp),%rdi # Pass its address. 562 563 call __generic_releasestack 564 565 subq 0(%rsp),%rax # Subtract available space. 566 addq $BACKOFF,%rax # Back off 1024 bytes. 567.LEHE0: 568 X86_64_SAVE_NEW_STACK_BOUNDARY (ax) 569 570 addq $16,%rsp # Remove values from stack. 571 572 # We need to restore the old stack pointer, which is in %rbp, 573 # before we unblock signals. We also need to restore %rax and 574 # %rdx after we unblock signals but before we return. Do this 575 # by moving %rax and %rdx from the current stack to the old 576 # stack. 577 578 popq %rdx # Pop return value from current stack. 579 popq %rax 580 581 movq %rbp,%rsp # Restore stack pointer. 582 583 # Now (%rsp & 16) == 8. 584 585 subq $8,%rsp # For alignment. 586 pushq %rax # Push return value on old stack. 587 pushq %rdx 588 589 call __morestack_unblock_signals 590 591 popq %rdx # Restore return value. 592 popq %rax 593 addq $8,%rsp 594 595 .cfi_remember_state 596 popq %rbp 597 .cfi_restore %rbp 598 .cfi_def_cfa %rsp, 16 599 ret # Return to caller, which will 600 # immediately return. 601 602# This is the cleanup code called by the stack unwinder when unwinding 603# through the code between .LEHB0 and .LEHE0 above. 604 605.L1: 606 .cfi_restore_state 607 subq $16,%rsp # Maintain 16 byte alignment. 608 movq %rax,(%rsp) # Save exception header. 609 movq %rbp,%rdi # Stack pointer after resume. 610 call __generic_findstack 611 movq %rbp,%rcx # Get the stack pointer. 612 subq %rax,%rcx # Subtract available space. 613 addq $BACKOFF,%rcx # Back off 1024 bytes. 614 X86_64_SAVE_NEW_STACK_BOUNDARY (cx) 615 movq (%rsp),%rdi # Restore exception data for call. 616#ifdef __PIC__ 617 call _Unwind_Resume@PLT # Resume unwinding. 618#else 619 call _Unwind_Resume # Resume unwinding. 620#endif 621 622#endif /* defined(__x86_64__) */ 623 624 .cfi_endproc 625#ifdef __ELF__ 626 .size __morestack, . - __morestack 627#endif 628 629#if !defined(__x86_64__) && defined(__PIC__) 630# Output the thunk to get PC into bx, since we use it above. 631 .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat 632 .globl __x86.get_pc_thunk.bx 633 .hidden __x86.get_pc_thunk.bx 634#ifdef __ELF__ 635 .type __x86.get_pc_thunk.bx, @function 636#endif 637__x86.get_pc_thunk.bx: 638 .cfi_startproc 639 movl (%esp), %ebx 640 ret 641 .cfi_endproc 642#ifdef __ELF__ 643 .size __x86.get_pc_thunk.bx, . - __x86.get_pc_thunk.bx 644#endif 645#endif 646 647# The exception table. This tells the personality routine to execute 648# the exception handler. 649 650 .section .gcc_except_table,"a",@progbits 651 .align 4 652.LLSDA1: 653 .byte 0xff # @LPStart format (omit) 654 .byte 0xff # @TType format (omit) 655 .byte 0x1 # call-site format (uleb128) 656 .uleb128 .LLSDACSE1-.LLSDACSB1 # Call-site table length 657.LLSDACSB1: 658 .uleb128 .LEHB0-.LFB1 # region 0 start 659 .uleb128 .LEHE0-.LEHB0 # length 660 .uleb128 .L1-.LFB1 # landing pad 661 .uleb128 0 # action 662.LLSDACSE1: 663 664 665 .global __gcc_personality_v0 666#ifdef __PIC__ 667 # Build a position independent reference to the basic 668 # personality function. 669 .hidden DW.ref.__gcc_personality_v0 670 .weak DW.ref.__gcc_personality_v0 671 .section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat 672 .type DW.ref.__gcc_personality_v0, @object 673DW.ref.__gcc_personality_v0: 674#ifndef __LP64__ 675 .align 4 676 .size DW.ref.__gcc_personality_v0, 4 677 .long __gcc_personality_v0 678#else 679 .align 8 680 .size DW.ref.__gcc_personality_v0, 8 681 .quad __gcc_personality_v0 682#endif 683#endif 684 685#if defined __x86_64__ && defined __LP64__ 686 687# This entry point is used for the large model. With this entry point 688# the upper 32 bits of %r10 hold the argument size and the lower 32 689# bits hold the new stack frame size. There doesn't seem to be a way 690# to know in the assembler code that we are assembling for the large 691# model, and there doesn't seem to be a large model multilib anyhow. 692# If one is developed, then the non-PIC code is probably OK since we 693# will probably be close to the morestack code, but the PIC code 694# almost certainly needs to be changed. FIXME. 695 696 .text 697 .global __morestack_large_model 698 .hidden __morestack_large_model 699 700#ifdef __ELF__ 701 .type __morestack_large_model,@function 702#endif 703 704__morestack_large_model: 705 706 .cfi_startproc 707 _CET_ENDBR 708 709 movq %r10, %r11 710 andl $0xffffffff, %r10d 711 sarq $32, %r11 712 jmp __morestack 713 714 .cfi_endproc 715#ifdef __ELF__ 716 .size __morestack_large_model, . - __morestack_large_model 717#endif 718 719#endif /* __x86_64__ && __LP64__ */ 720 721# Initialize the stack test value when the program starts or when a 722# new thread starts. We don't know how large the main stack is, so we 723# guess conservatively. We might be able to use getrlimit here. 724 725 .text 726 .global __stack_split_initialize 727 .hidden __stack_split_initialize 728 729#ifdef __ELF__ 730 .type __stack_split_initialize, @function 731#endif 732 733__stack_split_initialize: 734 _CET_ENDBR 735 736#ifndef __x86_64__ 737 738 leal -16000(%esp),%eax # We should have at least 16K. 739 movl %eax,%gs:0x30 740 subl $4,%esp # Align stack. 741 pushl $16000 742 pushl %esp 743#ifdef __PIC__ 744 call __generic_morestack_set_initial_sp@PLT 745#else 746 call __generic_morestack_set_initial_sp 747#endif 748 addl $12,%esp 749 ret 750 751#else /* defined(__x86_64__) */ 752 753 leaq -16000(%rsp),%rax # We should have at least 16K. 754 X86_64_SAVE_NEW_STACK_BOUNDARY (ax) 755 subq $8,%rsp # Align stack. 756 movq %rsp,%rdi 757 movq $16000,%rsi 758#ifdef __PIC__ 759 call __generic_morestack_set_initial_sp@PLT 760#else 761 call __generic_morestack_set_initial_sp 762#endif 763 addq $8,%rsp 764 ret 765 766#endif /* defined(__x86_64__) */ 767 768#ifdef __ELF__ 769 .size __stack_split_initialize, . - __stack_split_initialize 770#endif 771 772# Routines to get and set the guard, for __splitstack_getcontext, 773# __splitstack_setcontext, and __splitstack_makecontext. 774 775# void *__morestack_get_guard (void) returns the current stack guard. 776 .text 777 .global __morestack_get_guard 778 .hidden __morestack_get_guard 779 780#ifdef __ELF__ 781 .type __morestack_get_guard,@function 782#endif 783 784__morestack_get_guard: 785 786#ifndef __x86_64__ 787 movl %gs:0x30,%eax 788#else 789#ifdef __LP64__ 790 movq %fs:0x70,%rax 791#else 792 movl %fs:0x40,%eax 793#endif 794#endif 795 ret 796 797#ifdef __ELF__ 798 .size __morestack_get_guard, . - __morestack_get_guard 799#endif 800 801# void __morestack_set_guard (void *) sets the stack guard. 802 .global __morestack_set_guard 803 .hidden __morestack_set_guard 804 805#ifdef __ELF__ 806 .type __morestack_set_guard,@function 807#endif 808 809__morestack_set_guard: 810 811#ifndef __x86_64__ 812 movl 4(%esp),%eax 813 movl %eax,%gs:0x30 814#else 815 X86_64_SAVE_NEW_STACK_BOUNDARY (di) 816#endif 817 ret 818 819#ifdef __ELF__ 820 .size __morestack_set_guard, . - __morestack_set_guard 821#endif 822 823# void *__morestack_make_guard (void *, size_t) returns the stack 824# guard value for a stack. 825 .global __morestack_make_guard 826 .hidden __morestack_make_guard 827 828#ifdef __ELF__ 829 .type __morestack_make_guard,@function 830#endif 831 832__morestack_make_guard: 833 834#ifndef __x86_64__ 835 movl 4(%esp),%eax 836 subl 8(%esp),%eax 837 addl $BACKOFF,%eax 838#else 839 subq %rsi,%rdi 840 addq $BACKOFF,%rdi 841 movq %rdi,%rax 842#endif 843 ret 844 845#ifdef __ELF__ 846 .size __morestack_make_guard, . - __morestack_make_guard 847#endif 848 849# Make __stack_split_initialize a high priority constructor. FIXME: 850# This is ELF specific. 851 852#if HAVE_INITFINI_ARRAY_SUPPORT 853 .section .init_array.00000,"aw",@progbits 854#else 855 .section .ctors.65535,"aw",@progbits 856#endif 857 858#ifndef __LP64__ 859 .align 4 860 .long __stack_split_initialize 861 .long __morestack_load_mmap 862#else 863 .align 8 864 .quad __stack_split_initialize 865 .quad __morestack_load_mmap 866#endif 867 868#if defined(__ELF__) && defined(__linux__) 869 .section .note.GNU-stack,"",@progbits 870 .section .note.GNU-split-stack,"",@progbits 871 .section .note.GNU-no-split-stack,"",@progbits 872#endif 873