1#ifdef __powerpc64__ 2# PowerPC64 support for -fsplit-stack. 3# Copyright (C) 2009-2020 Free Software Foundation, Inc. 4# Contributed by Alan Modra <amodra@gmail.com>. 5 6# This file is part of GCC. 7 8# GCC is free software; you can redistribute it and/or modify it under 9# the terms of the GNU General Public License as published by the Free 10# Software Foundation; either version 3, or (at your option) any later 11# version. 12 13# GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14# WARRANTY; without even the implied warranty of MERCHANTABILITY or 15# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16# for more details. 17 18# Under Section 7 of GPL version 3, you are granted additional 19# permissions described in the GCC Runtime Library Exception, version 20# 3.1, as published by the Free Software Foundation. 21 22# You should have received a copy of the GNU General Public License and 23# a copy of the GCC Runtime Library Exception along with this program; 24# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 25# <http://www.gnu.org/licenses/>. 26 27#if _CALL_ELF == 2 28 .abiversion 2 29#define PARAMS 32 30#else 31#define PARAMS 48 32#endif 33#define MORESTACK_FRAMESIZE (PARAMS+96) 34#define PARAMREG_SAVE -MORESTACK_FRAMESIZE+PARAMS+0 35#define STATIC_CHAIN_SAVE -MORESTACK_FRAMESIZE+PARAMS+64 36#define R29_SAVE -MORESTACK_FRAMESIZE+PARAMS+72 37#define LINKREG_SAVE -MORESTACK_FRAMESIZE+PARAMS+80 38#define NEWSTACKSIZE_SAVE -MORESTACK_FRAMESIZE+PARAMS+88 39 40# Excess space needed to call ld.so resolver for lazy plt 41# resolution. Go uses sigaltstack so this doesn't need to 42# also cover signal frame size. 43#define BACKOFF 4096 44# Large excess allocated when calling non-split-stack code. 45#define NON_SPLIT_STACK 0x100000 46 47 48#if _CALL_ELF == 2 49 50#define BODY_LABEL(name) name 51 52#define ENTRY0(name) \ 53 .global name; \ 54 .hidden name; \ 55 .type name,@function; \ 56name##: 57 58#define ENTRY(name) \ 59 ENTRY0(name); \ 600: addis %r2,%r12,.TOC.-0b@ha; \ 61 addi %r2,%r2,.TOC.-0b@l; \ 62 .localentry name, .-name 63 64#else 65 66#define BODY_LABEL(name) .L.##name 67 68#define ENTRY0(name) \ 69 .global name; \ 70 .hidden name; \ 71 .type name,@function; \ 72 .pushsection ".opd","aw"; \ 73 .p2align 3; \ 74name##: .quad BODY_LABEL (name), .TOC.@tocbase, 0; \ 75 .popsection; \ 76BODY_LABEL(name)##: 77 78#define ENTRY(name) ENTRY0(name) 79 80#endif 81 82#define SIZE(name) .size name, .-BODY_LABEL(name) 83 84 85 .text 86# Just like __morestack, but with larger excess allocation 87ENTRY0(__morestack_non_split) 88.LFB1: 89 .cfi_startproc 90# We use a cleanup to restore the tcbhead_t.__private_ss if 91# an exception is thrown through this code. 92#ifdef __PIC__ 93 .cfi_personality 0x9b,DW.ref.__gcc_personality_v0 94 .cfi_lsda 0x1b,.LLSDA1 95#else 96 .cfi_personality 0x3,__gcc_personality_v0 97 .cfi_lsda 0x3,.LLSDA1 98#endif 99# LR is already saved by the split-stack prologue code. 100# We may as well have the unwinder skip over the call in the 101# prologue too. 102 .cfi_offset %lr,16 103 104 addis %r12,%r12,-NON_SPLIT_STACK@h 105 SIZE (__morestack_non_split) 106# Fall through into __morestack 107 108 109# This function is called with non-standard calling conventions. 110# On entry, r12 is the requested stack pointer. One version of the 111# split-stack prologue that calls __morestack looks like 112# ld %r0,-0x7000-64(%r13) 113# addis %r12,%r1,-allocate@ha 114# addi %r12,%r12,-allocate@l 115# cmpld %r12,%r0 116# bge+ enough 117# mflr %r0 118# std %r0,16(%r1) 119# bl __morestack 120# ld %r0,16(%r1) 121# mtlr %r0 122# blr 123# enough: 124# The normal function prologue follows here, with a small addition at 125# the end to set up the arg pointer. The arg pointer is set up with: 126# addi %r12,%r1,offset 127# bge %cr7,.+8 128# mr %r12,%r29 129# 130# Note that the lr save slot 16(%r1) has already been used. 131# r3 thru r11 possibly contain arguments and a static chain 132# pointer for the function we're calling, so must be preserved. 133# cr7 must also be preserved. 134 135ENTRY0(__morestack) 136# Save parameter passing registers, our arguments, lr, r29 137# and use r29 as a frame pointer. 138 std %r3,PARAMREG_SAVE+0(%r1) 139 sub %r3,%r1,%r12 # calculate requested stack size 140 mflr %r12 141 std %r4,PARAMREG_SAVE+8(%r1) 142 std %r5,PARAMREG_SAVE+16(%r1) 143 std %r6,PARAMREG_SAVE+24(%r1) 144 std %r7,PARAMREG_SAVE+32(%r1) 145 addi %r3,%r3,BACKOFF 146 std %r8,PARAMREG_SAVE+40(%r1) 147 std %r9,PARAMREG_SAVE+48(%r1) 148 std %r10,PARAMREG_SAVE+56(%r1) 149 std %r11,STATIC_CHAIN_SAVE(%r1) 150 std %r29,R29_SAVE(%r1) 151 std %r12,LINKREG_SAVE(%r1) 152 std %r3,NEWSTACKSIZE_SAVE(%r1) # new stack size 153 mr %r29,%r1 154 .cfi_offset %r29,R29_SAVE 155 .cfi_def_cfa_register %r29 156 stdu %r1,-MORESTACK_FRAMESIZE(%r1) 157 158 # void __morestack_block_signals (void) 159 bl __morestack_block_signals 160 161 # void *__generic_morestack (size_t *pframe_size, 162 # void *old_stack, 163 # size_t param_size) 164 addi %r3,%r29,NEWSTACKSIZE_SAVE 165 mr %r4,%r29 166 li %r5,0 # no copying from old stack 167 bl __generic_morestack 168 169# Start using new stack 170 stdu %r29,-32(%r3) # back-chain 171 mr %r1,%r3 172 173# Set __private_ss stack guard for the new stack. 174 ld %r12,NEWSTACKSIZE_SAVE(%r29) # modified size 175 addi %r3,%r3,BACKOFF-32 176 sub %r3,%r3,%r12 177# Note that a signal frame has $pc pointing at the instruction 178# where the signal occurred. For something like a timer 179# interrupt this means the instruction has already executed, 180# thus the region starts at the instruction modifying 181# __private_ss, not one instruction after. 182.LEHB0: 183 std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 184 185 # void __morestack_unblock_signals (void) 186 bl __morestack_unblock_signals 187 188# Set up for a call to the target function, located 3 189# instructions after __morestack's return address. 190# 191 ld %r12,LINKREG_SAVE(%r29) 192 ld %r3,PARAMREG_SAVE+0(%r29) # restore arg regs 193 ld %r4,PARAMREG_SAVE+8(%r29) 194 ld %r5,PARAMREG_SAVE+16(%r29) 195 ld %r6,PARAMREG_SAVE+24(%r29) 196 ld %r7,PARAMREG_SAVE+32(%r29) 197 ld %r8,PARAMREG_SAVE+40(%r29) 198 ld %r9,PARAMREG_SAVE+48(%r29) 199 addi %r0,%r12,12 # add 3 instructions 200 ld %r10,PARAMREG_SAVE+56(%r29) 201 ld %r11,STATIC_CHAIN_SAVE(%r29) 202 cmpld %cr7,%r12,%r0 # indicate we were called 203 mtctr %r0 204 bctrl # call caller! 205 206# On return, save regs possibly used to return a value, and 207# possibly trashed by calls to __morestack_block_signals, 208# __generic_releasestack and __morestack_unblock_signals. 209# Assume those calls don't use vector or floating point regs. 210 std %r3,PARAMREG_SAVE+0(%r29) 211 std %r4,PARAMREG_SAVE+8(%r29) 212 std %r5,PARAMREG_SAVE+16(%r29) 213 std %r6,PARAMREG_SAVE+24(%r29) 214#if _CALL_ELF == 2 215 std %r7,PARAMREG_SAVE+32(%r29) 216 std %r8,PARAMREG_SAVE+40(%r29) 217 std %r9,PARAMREG_SAVE+48(%r29) 218 std %r10,PARAMREG_SAVE+56(%r29) 219#endif 220 221 bl __morestack_block_signals 222 223 # void *__generic_releasestack (size_t *pavailable) 224 addi %r3,%r29,NEWSTACKSIZE_SAVE 225 bl __generic_releasestack 226 227# Reset __private_ss stack guard to value for old stack 228 ld %r12,NEWSTACKSIZE_SAVE(%r29) 229 addi %r3,%r3,BACKOFF 230 sub %r3,%r3,%r12 231.LEHE0: 232 std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 233 234 bl __morestack_unblock_signals 235 236# Use old stack again. 237 mr %r1,%r29 238 239# Restore return value regs, and return. 240 ld %r0,LINKREG_SAVE(%r29) 241 mtlr %r0 242 ld %r3,PARAMREG_SAVE+0(%r29) 243 ld %r4,PARAMREG_SAVE+8(%r29) 244 ld %r5,PARAMREG_SAVE+16(%r29) 245 ld %r6,PARAMREG_SAVE+24(%r29) 246#if _CALL_ELF == 2 247 ld %r7,PARAMREG_SAVE+32(%r29) 248 ld %r8,PARAMREG_SAVE+40(%r29) 249 ld %r9,PARAMREG_SAVE+48(%r29) 250 ld %r10,PARAMREG_SAVE+56(%r29) 251#endif 252 ld %r29,R29_SAVE(%r29) 253 .cfi_def_cfa_register %r1 254 blr 255 256# This is the cleanup code called by the stack unwinder when 257# unwinding through code between .LEHB0 and .LEHE0 above. 258cleanup: 259 .cfi_def_cfa_register %r29 260 std %r3,PARAMREG_SAVE(%r29) # Save exception header 261 # size_t __generic_findstack (void *stack) 262 mr %r3,%r29 263 bl __generic_findstack 264 sub %r3,%r29,%r3 265 addi %r3,%r3,BACKOFF 266 std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 267 ld %r3,PARAMREG_SAVE(%r29) 268 bl _Unwind_Resume 269 nop 270 .cfi_endproc 271 SIZE (__morestack) 272 273 274 .section .gcc_except_table,"a",@progbits 275 .p2align 2 276.LLSDA1: 277 .byte 0xff # @LPStart format (omit) 278 .byte 0xff # @TType format (omit) 279 .byte 0x1 # call-site format (uleb128) 280 .uleb128 .LLSDACSE1-.LLSDACSB1 # Call-site table length 281.LLSDACSB1: 282 .uleb128 .LEHB0-.LFB1 # region 0 start 283 .uleb128 .LEHE0-.LEHB0 # length 284 .uleb128 cleanup-.LFB1 # landing pad 285 .uleb128 0 # no action, ie. a cleanup 286.LLSDACSE1: 287 288 289#ifdef __PIC__ 290# Build a position independent reference to the personality function. 291 .hidden DW.ref.__gcc_personality_v0 292 .weak DW.ref.__gcc_personality_v0 293 .section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat 294 .p2align 3 295DW.ref.__gcc_personality_v0: 296 .quad __gcc_personality_v0 297 .type DW.ref.__gcc_personality_v0, @object 298 .size DW.ref.__gcc_personality_v0, 8 299#endif 300 301 302 .text 303# Initialize the stack guard when the program starts or when a 304# new thread starts. This is called from a constructor. 305# void __stack_split_initialize (void) 306ENTRY(__stack_split_initialize) 307 .cfi_startproc 308 addi %r3,%r1,-0x4000 # We should have at least 16K. 309 std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 310 # void __generic_morestack_set_initial_sp (void *sp, size_t len) 311 mr %r3,%r1 312 li %r4, 0x4000 313 b __generic_morestack_set_initial_sp 314# The lack of .cfi_endproc here is deliberate. This function and the 315# following ones can all use the default FDE. 316 SIZE (__stack_split_initialize) 317 318 319# Return current __private_ss 320# void *__morestack_get_guard (void) 321ENTRY0(__morestack_get_guard) 322 ld %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 323 blr 324 SIZE (__morestack_get_guard) 325 326 327# Set __private_ss 328# void __morestack_set_guard (void *ptr) 329ENTRY0(__morestack_set_guard) 330 std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 331 blr 332 SIZE (__morestack_set_guard) 333 334 335# Return the stack guard value for given stack 336# void *__morestack_make_guard (void *stack, size_t size) 337ENTRY0(__morestack_make_guard) 338 sub %r3,%r3,%r4 339 addi %r3,%r3,BACKOFF 340 blr 341 .cfi_endproc 342 SIZE (__morestack_make_guard) 343 344 345# Make __stack_split_initialize a high priority constructor. 346 .section .ctors.65535,"aw",@progbits 347 .p2align 3 348 .quad __stack_split_initialize 349 .quad __morestack_load_mmap 350 351 .section .note.GNU-stack,"",@progbits 352 .section .note.GNU-split-stack,"",@progbits 353 .section .note.GNU-no-split-stack,"",@progbits 354#endif /* __powerpc64__ */ 355