123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- #ifdef __powerpc64__
- # PowerPC64 support for -fsplit-stack.
- # Copyright (C) 2009-2022 Free Software Foundation, Inc.
- # Contributed by Alan Modra <amodra@gmail.com>.
- # This file is part of GCC.
- # GCC is free software; you can redistribute it and/or modify it under
- # the terms of the GNU General Public License as published by the Free
- # Software Foundation; either version 3, or (at your option) any later
- # version.
- # GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- # WARRANTY; without even the implied warranty of MERCHANTABILITY or
- # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- # for more details.
- # Under Section 7 of GPL version 3, you are granted additional
- # permissions described in the GCC Runtime Library Exception, version
- # 3.1, as published by the Free Software Foundation.
- # You should have received a copy of the GNU General Public License and
- # a copy of the GCC Runtime Library Exception along with this program;
- # see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- # <http://www.gnu.org/licenses/>.
- #include <auto-host.h>
- #if _CALL_ELF == 2
- .abiversion 2
- #define PARAMS 32
- #else
- #define PARAMS 48
- #endif
- #define MORESTACK_FRAMESIZE (PARAMS+96)
- #define R2_SAVE -MORESTACK_FRAMESIZE+PARAMS-8
- #define PARAMREG_SAVE -MORESTACK_FRAMESIZE+PARAMS+0
- #define STATIC_CHAIN_SAVE -MORESTACK_FRAMESIZE+PARAMS+64
- #define R29_SAVE -MORESTACK_FRAMESIZE+PARAMS+72
- #define LINKREG_SAVE -MORESTACK_FRAMESIZE+PARAMS+80
- #define NEWSTACKSIZE_SAVE -MORESTACK_FRAMESIZE+PARAMS+88
- # Excess space needed to call ld.so resolver for lazy plt
- # resolution. Go uses sigaltstack so this doesn't need to
- # also cover signal frame size.
- #define BACKOFF 4096
- # Large excess allocated when calling non-split-stack code.
- #define NON_SPLIT_STACK 0x100000
- #if _CALL_ELF == 2
- #define BODY_LABEL(name) name
- #define ENTRY0(name) \
- .global name; \
- .hidden name; \
- .type name,@function; \
- name##:
- #ifdef __PCREL__
- #define ENTRY(name) \
- ENTRY0(name); \
- .localentry name, 1
- #define JUMP_TARGET(name) name##@notoc
- #else
- #define ENTRY(name) \
- ENTRY0(name); \
- 0: addis %r2,%r12,.TOC.-0b@ha; \
- addi %r2,%r2,.TOC.-0b@l; \
- .localentry name, .-name
- #endif
- #else
- #define BODY_LABEL(name) .L.##name
- #define ENTRY0(name) \
- .global name; \
- .hidden name; \
- .type name,@function; \
- .pushsection ".opd","aw"; \
- .p2align 3; \
- name##: .quad BODY_LABEL (name), .TOC.@tocbase, 0; \
- .popsection; \
- BODY_LABEL(name)##:
- #define ENTRY(name) ENTRY0(name)
- #endif
- #define SIZE(name) .size name, .-BODY_LABEL(name)
- #ifndef JUMP_TARGET
- #define JUMP_TARGET(name) name
- #endif
- .text
- # Just like __morestack, but with larger excess allocation
- ENTRY0(__morestack_non_split)
- .LFB1:
- .cfi_startproc
- # We use a cleanup to restore the tcbhead_t.__private_ss if
- # an exception is thrown through this code.
- #ifdef __PIC__
- .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
- .cfi_lsda 0x1b,.LLSDA1
- #else
- .cfi_personality 0x3,__gcc_personality_v0
- .cfi_lsda 0x3,.LLSDA1
- #endif
- # LR is already saved by the split-stack prologue code.
- # We may as well have the unwinder skip over the call in the
- # prologue too.
- .cfi_offset %lr,16
- addis %r12,%r12,-NON_SPLIT_STACK@h
- SIZE (__morestack_non_split)
- # Fall through into __morestack
- # This function is called with non-standard calling conventions.
- # On entry, r12 is the requested stack pointer. One version of the
- # split-stack prologue that calls __morestack looks like
- # ld %r0,-0x7000-64(%r13)
- # addis %r12,%r1,-allocate@ha
- # addi %r12,%r12,-allocate@l
- # cmpld %r12,%r0
- # bge+ enough
- # mflr %r0
- # std %r0,16(%r1)
- # bl __morestack
- # ld %r0,16(%r1)
- # mtlr %r0
- # blr
- # enough:
- # The normal function prologue follows here, with a small addition at
- # the end to set up the arg pointer. The arg pointer is set up with:
- # addi %r12,%r1,offset
- # bge %cr7,.+8
- # mr %r12,%r29
- #
- # Note that the lr save slot 16(%r1) has already been used.
- # r3 thru r11 possibly contain arguments and a static chain
- # pointer for the function we're calling, so must be preserved.
- # cr7 must also be preserved.
- ENTRY0(__morestack)
- #if _CALL_ELF == 2
- # Functions with localentry bits of zero cannot make calls if those
- # calls might change r2. This is true generally, and also true for
- # __morestack with its special calling convention. When __morestack's
- # caller is non-pcrel but libgcc is pcrel, the functions called here
- # might modify r2. r2 must be preserved on exit, and also restored
- # for the call back to our caller.
- std %r2,R2_SAVE(%r1)
- #endif
- # Save parameter passing registers, our arguments, lr, r29
- # and use r29 as a frame pointer.
- std %r3,PARAMREG_SAVE+0(%r1)
- sub %r3,%r1,%r12 # calculate requested stack size
- mflr %r12
- std %r4,PARAMREG_SAVE+8(%r1)
- std %r5,PARAMREG_SAVE+16(%r1)
- std %r6,PARAMREG_SAVE+24(%r1)
- std %r7,PARAMREG_SAVE+32(%r1)
- addi %r3,%r3,BACKOFF
- std %r8,PARAMREG_SAVE+40(%r1)
- std %r9,PARAMREG_SAVE+48(%r1)
- std %r10,PARAMREG_SAVE+56(%r1)
- std %r11,STATIC_CHAIN_SAVE(%r1)
- std %r29,R29_SAVE(%r1)
- std %r12,LINKREG_SAVE(%r1)
- std %r3,NEWSTACKSIZE_SAVE(%r1) # new stack size
- mr %r29,%r1
- #if _CALL_ELF == 2
- .cfi_offset %r2,R2_SAVE
- #endif
- .cfi_offset %r29,R29_SAVE
- .cfi_def_cfa_register %r29
- stdu %r1,-MORESTACK_FRAMESIZE(%r1)
- #if _CALL_ELF == 2 && !defined __PCREL__
- # If this isn't a pcrel libgcc then the functions we call here will
- # require r2 to be valid. If __morestack is called from pcrel code r2
- # won't be valid. Set it up.
- bcl 20,31,1f
- 1:
- mflr %r12
- addis %r2,%r12,.TOC.-1b@ha
- addi %r2,%r2,.TOC.-1b@l
- #endif
- # void __morestack_block_signals (void)
- bl JUMP_TARGET(__morestack_block_signals)
- # void *__generic_morestack (size_t *pframe_size,
- # void *old_stack,
- # size_t param_size)
- addi %r3,%r29,NEWSTACKSIZE_SAVE
- mr %r4,%r29
- li %r5,0 # no copying from old stack
- bl JUMP_TARGET(__generic_morestack)
- # Start using new stack
- stdu %r29,-32(%r3) # back-chain
- mr %r1,%r3
- # Set __private_ss stack guard for the new stack.
- ld %r12,NEWSTACKSIZE_SAVE(%r29) # modified size
- addi %r3,%r3,BACKOFF-32
- sub %r3,%r3,%r12
- # Note that a signal frame has $pc pointing at the instruction
- # where the signal occurred. For something like a timer
- # interrupt this means the instruction has already executed,
- # thus the region starts at the instruction modifying
- # __private_ss, not one instruction after.
- .LEHB0:
- std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
- # void __morestack_unblock_signals (void)
- bl JUMP_TARGET(__morestack_unblock_signals)
- # Set up for a call to the target function, located 3
- # instructions after __morestack's return address.
- #
- ld %r12,LINKREG_SAVE(%r29)
- #if _CALL_ELF == 2
- ld %r2,R2_SAVE(%r29)
- #endif
- ld %r3,PARAMREG_SAVE+0(%r29) # restore arg regs
- ld %r4,PARAMREG_SAVE+8(%r29)
- ld %r5,PARAMREG_SAVE+16(%r29)
- ld %r6,PARAMREG_SAVE+24(%r29)
- ld %r7,PARAMREG_SAVE+32(%r29)
- ld %r8,PARAMREG_SAVE+40(%r29)
- ld %r9,PARAMREG_SAVE+48(%r29)
- addi %r0,%r12,12 # add 3 instructions
- ld %r10,PARAMREG_SAVE+56(%r29)
- ld %r11,STATIC_CHAIN_SAVE(%r29)
- cmpld %cr7,%r12,%r0 # indicate we were called
- mtctr %r0
- bctrl # call caller!
- # On return, save regs possibly used to return a value, and
- # possibly trashed by calls to __morestack_block_signals,
- # __generic_releasestack and __morestack_unblock_signals.
- # Assume those calls don't use vector or floating point regs.
- std %r3,PARAMREG_SAVE+0(%r29)
- std %r4,PARAMREG_SAVE+8(%r29)
- std %r5,PARAMREG_SAVE+16(%r29)
- std %r6,PARAMREG_SAVE+24(%r29)
- #if _CALL_ELF == 2
- std %r7,PARAMREG_SAVE+32(%r29)
- std %r8,PARAMREG_SAVE+40(%r29)
- std %r9,PARAMREG_SAVE+48(%r29)
- std %r10,PARAMREG_SAVE+56(%r29)
- #endif
- #if _CALL_ELF == 2 && !defined __PCREL__
- # r2 was restored for calling back into our caller. Set it up again.
- bcl 20,31,1f
- 1:
- mflr %r12
- addis %r2,%r12,.TOC.-1b@ha
- addi %r2,%r2,.TOC.-1b@l
- #endif
- bl JUMP_TARGET(__morestack_block_signals)
- # void *__generic_releasestack (size_t *pavailable)
- addi %r3,%r29,NEWSTACKSIZE_SAVE
- bl JUMP_TARGET(__generic_releasestack)
- # Reset __private_ss stack guard to value for old stack
- ld %r12,NEWSTACKSIZE_SAVE(%r29)
- addi %r3,%r3,BACKOFF
- sub %r3,%r3,%r12
- .LEHE0:
- std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
- bl JUMP_TARGET(__morestack_unblock_signals)
- # Use old stack again.
- mr %r1,%r29
- # Restore return value regs, and return.
- ld %r0,LINKREG_SAVE(%r29)
- mtlr %r0
- #if _CALL_ELF == 2
- ld %r2,R2_SAVE(%r29)
- #endif
- ld %r3,PARAMREG_SAVE+0(%r29)
- ld %r4,PARAMREG_SAVE+8(%r29)
- ld %r5,PARAMREG_SAVE+16(%r29)
- ld %r6,PARAMREG_SAVE+24(%r29)
- #if _CALL_ELF == 2
- ld %r7,PARAMREG_SAVE+32(%r29)
- ld %r8,PARAMREG_SAVE+40(%r29)
- ld %r9,PARAMREG_SAVE+48(%r29)
- ld %r10,PARAMREG_SAVE+56(%r29)
- #endif
- ld %r29,R29_SAVE(%r29)
- .cfi_def_cfa_register %r1
- blr
- # This is the cleanup code called by the stack unwinder when
- # unwinding through code between .LEHB0 and .LEHE0 above.
- cleanup:
- .cfi_def_cfa_register %r29
- std %r3,PARAMREG_SAVE(%r29) # Save exception header
- # size_t __generic_findstack (void *stack)
- mr %r3,%r29
- bl JUMP_TARGET(__generic_findstack)
- sub %r3,%r29,%r3
- addi %r3,%r3,BACKOFF
- std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
- ld %r3,PARAMREG_SAVE(%r29)
- bl JUMP_TARGET(_Unwind_Resume)
- #ifndef __PCREL__
- nop
- #endif
- .cfi_endproc
- SIZE (__morestack)
- .section .gcc_except_table,"a",@progbits
- .p2align 2
- .LLSDA1:
- .byte 0xff # @LPStart format (omit)
- .byte 0xff # @TType format (omit)
- .byte 0x1 # call-site format (uleb128)
- .uleb128 .LLSDACSE1-.LLSDACSB1 # Call-site table length
- .LLSDACSB1:
- .uleb128 .LEHB0-.LFB1 # region 0 start
- .uleb128 .LEHE0-.LEHB0 # length
- .uleb128 cleanup-.LFB1 # landing pad
- .uleb128 0 # no action, ie. a cleanup
- .LLSDACSE1:
- #ifdef __PIC__
- # Build a position independent reference to the personality function.
- .hidden DW.ref.__gcc_personality_v0
- .weak DW.ref.__gcc_personality_v0
- .section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat
- .p2align 3
- DW.ref.__gcc_personality_v0:
- .quad __gcc_personality_v0
- .type DW.ref.__gcc_personality_v0, @object
- .size DW.ref.__gcc_personality_v0, 8
- #endif
- .text
- # Initialize the stack guard when the program starts or when a
- # new thread starts. This is called from a constructor.
- # void __stack_split_initialize (void)
- ENTRY(__stack_split_initialize)
- .cfi_startproc
- addi %r3,%r1,-0x4000 # We should have at least 16K.
- std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
- # void __generic_morestack_set_initial_sp (void *sp, size_t len)
- mr %r3,%r1
- li %r4, 0x4000
- b JUMP_TARGET(__generic_morestack_set_initial_sp)
- # The lack of .cfi_endproc here is deliberate. This function and the
- # following ones can all use the default FDE.
- SIZE (__stack_split_initialize)
- # Return current __private_ss
- # void *__morestack_get_guard (void)
- ENTRY0(__morestack_get_guard)
- ld %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
- blr
- SIZE (__morestack_get_guard)
- # Set __private_ss
- # void __morestack_set_guard (void *ptr)
- ENTRY0(__morestack_set_guard)
- std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
- blr
- SIZE (__morestack_set_guard)
- # Return the stack guard value for given stack
- # void *__morestack_make_guard (void *stack, size_t size)
- ENTRY0(__morestack_make_guard)
- sub %r3,%r3,%r4
- addi %r3,%r3,BACKOFF
- blr
- .cfi_endproc
- SIZE (__morestack_make_guard)
- # Make __stack_split_initialize a high priority constructor.
- #if HAVE_INITFINI_ARRAY_SUPPORT
- .section .init_array.00000,"aw",@progbits
- #else
- .section .ctors.65535,"aw",@progbits
- #endif
- .p2align 3
- .quad __stack_split_initialize
- .quad __morestack_load_mmap
- .section .note.GNU-stack,"",@progbits
- .section .note.GNU-split-stack,"",@progbits
- .section .note.GNU-no-split-stack,"",@progbits
- #endif /* __powerpc64__ */
|