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 R2_SAVE -MORESTACK_FRAMESIZE+PARAMS-8 35#define PARAMREG_SAVE -MORESTACK_FRAMESIZE+PARAMS+0 36#define STATIC_CHAIN_SAVE -MORESTACK_FRAMESIZE+PARAMS+64 37#define R29_SAVE -MORESTACK_FRAMESIZE+PARAMS+72 38#define LINKREG_SAVE -MORESTACK_FRAMESIZE+PARAMS+80 39#define NEWSTACKSIZE_SAVE -MORESTACK_FRAMESIZE+PARAMS+88 40 41# Excess space needed to call ld.so resolver for lazy plt 42# resolution. Go uses sigaltstack so this doesn't need to 43# also cover signal frame size. 44#define BACKOFF 4096 45# Large excess allocated when calling non-split-stack code. 46#define NON_SPLIT_STACK 0x100000 47 48 49#if _CALL_ELF == 2 50 51#define BODY_LABEL(name) name 52 53#define ENTRY0(name) \ 54 .global name; \ 55 .hidden name; \ 56 .type name,@function; \ 57name##: 58 59#ifdef __PCREL__ 60#define ENTRY(name) \ 61 ENTRY0(name); \ 62 .localentry name, 1 63#define JUMP_TARGET(name) name##@notoc 64#else 65#define ENTRY(name) \ 66 ENTRY0(name); \ 670: addis %r2,%r12,.TOC.-0b@ha; \ 68 addi %r2,%r2,.TOC.-0b@l; \ 69 .localentry name, .-name 70#endif 71 72#else 73 74#define BODY_LABEL(name) .L.##name 75 76#define ENTRY0(name) \ 77 .global name; \ 78 .hidden name; \ 79 .type name,@function; \ 80 .pushsection ".opd","aw"; \ 81 .p2align 3; \ 82name##: .quad BODY_LABEL (name), .TOC.@tocbase, 0; \ 83 .popsection; \ 84BODY_LABEL(name)##: 85 86#define ENTRY(name) ENTRY0(name) 87 88#endif 89 90#define SIZE(name) .size name, .-BODY_LABEL(name) 91 92#ifndef JUMP_TARGET 93#define JUMP_TARGET(name) name 94#endif 95 96 .text 97# Just like __morestack, but with larger excess allocation 98ENTRY0(__morestack_non_split) 99.LFB1: 100 .cfi_startproc 101# We use a cleanup to restore the tcbhead_t.__private_ss if 102# an exception is thrown through this code. 103#ifdef __PIC__ 104 .cfi_personality 0x9b,DW.ref.__gcc_personality_v0 105 .cfi_lsda 0x1b,.LLSDA1 106#else 107 .cfi_personality 0x3,__gcc_personality_v0 108 .cfi_lsda 0x3,.LLSDA1 109#endif 110# LR is already saved by the split-stack prologue code. 111# We may as well have the unwinder skip over the call in the 112# prologue too. 113 .cfi_offset %lr,16 114 115 addis %r12,%r12,-NON_SPLIT_STACK@h 116 SIZE (__morestack_non_split) 117# Fall through into __morestack 118 119 120# This function is called with non-standard calling conventions. 121# On entry, r12 is the requested stack pointer. One version of the 122# split-stack prologue that calls __morestack looks like 123# ld %r0,-0x7000-64(%r13) 124# addis %r12,%r1,-allocate@ha 125# addi %r12,%r12,-allocate@l 126# cmpld %r12,%r0 127# bge+ enough 128# mflr %r0 129# std %r0,16(%r1) 130# bl __morestack 131# ld %r0,16(%r1) 132# mtlr %r0 133# blr 134# enough: 135# The normal function prologue follows here, with a small addition at 136# the end to set up the arg pointer. The arg pointer is set up with: 137# addi %r12,%r1,offset 138# bge %cr7,.+8 139# mr %r12,%r29 140# 141# Note that the lr save slot 16(%r1) has already been used. 142# r3 thru r11 possibly contain arguments and a static chain 143# pointer for the function we're calling, so must be preserved. 144# cr7 must also be preserved. 145 146ENTRY0(__morestack) 147 148#if _CALL_ELF == 2 149# Functions with localentry bits of zero cannot make calls if those 150# calls might change r2. This is true generally, and also true for 151# __morestack with its special calling convention. When __morestack's 152# caller is non-pcrel but libgcc is pcrel, the functions called here 153# might modify r2. r2 must be preserved on exit, and also restored 154# for the call back to our caller. 155 std %r2,R2_SAVE(%r1) 156#endif 157 158# Save parameter passing registers, our arguments, lr, r29 159# and use r29 as a frame pointer. 160 std %r3,PARAMREG_SAVE+0(%r1) 161 sub %r3,%r1,%r12 # calculate requested stack size 162 mflr %r12 163 std %r4,PARAMREG_SAVE+8(%r1) 164 std %r5,PARAMREG_SAVE+16(%r1) 165 std %r6,PARAMREG_SAVE+24(%r1) 166 std %r7,PARAMREG_SAVE+32(%r1) 167 addi %r3,%r3,BACKOFF 168 std %r8,PARAMREG_SAVE+40(%r1) 169 std %r9,PARAMREG_SAVE+48(%r1) 170 std %r10,PARAMREG_SAVE+56(%r1) 171 std %r11,STATIC_CHAIN_SAVE(%r1) 172 std %r29,R29_SAVE(%r1) 173 std %r12,LINKREG_SAVE(%r1) 174 std %r3,NEWSTACKSIZE_SAVE(%r1) # new stack size 175 mr %r29,%r1 176#if _CALL_ELF == 2 177 .cfi_offset %r2,R2_SAVE 178#endif 179 .cfi_offset %r29,R29_SAVE 180 .cfi_def_cfa_register %r29 181 stdu %r1,-MORESTACK_FRAMESIZE(%r1) 182 183#if _CALL_ELF == 2 && !defined __PCREL__ 184# If this isn't a pcrel libgcc then the functions we call here will 185# require r2 to be valid. If __morestack is called from pcrel code r2 186# won't be valid. Set it up. 187 bcl 20,31,1f 1881: 189 mflr %r12 190 addis %r2,%r12,.TOC.-1b@ha 191 addi %r2,%r2,.TOC.-1b@l 192#endif 193 194 # void __morestack_block_signals (void) 195 bl JUMP_TARGET(__morestack_block_signals) 196 197 # void *__generic_morestack (size_t *pframe_size, 198 # void *old_stack, 199 # size_t param_size) 200 addi %r3,%r29,NEWSTACKSIZE_SAVE 201 mr %r4,%r29 202 li %r5,0 # no copying from old stack 203 bl JUMP_TARGET(__generic_morestack) 204 205# Start using new stack 206 stdu %r29,-32(%r3) # back-chain 207 mr %r1,%r3 208 209# Set __private_ss stack guard for the new stack. 210 ld %r12,NEWSTACKSIZE_SAVE(%r29) # modified size 211 addi %r3,%r3,BACKOFF-32 212 sub %r3,%r3,%r12 213# Note that a signal frame has $pc pointing at the instruction 214# where the signal occurred. For something like a timer 215# interrupt this means the instruction has already executed, 216# thus the region starts at the instruction modifying 217# __private_ss, not one instruction after. 218.LEHB0: 219 std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 220 221 # void __morestack_unblock_signals (void) 222 bl JUMP_TARGET(__morestack_unblock_signals) 223 224# Set up for a call to the target function, located 3 225# instructions after __morestack's return address. 226# 227 ld %r12,LINKREG_SAVE(%r29) 228#if _CALL_ELF == 2 229 ld %r2,R2_SAVE(%r29) 230#endif 231 ld %r3,PARAMREG_SAVE+0(%r29) # restore arg regs 232 ld %r4,PARAMREG_SAVE+8(%r29) 233 ld %r5,PARAMREG_SAVE+16(%r29) 234 ld %r6,PARAMREG_SAVE+24(%r29) 235 ld %r7,PARAMREG_SAVE+32(%r29) 236 ld %r8,PARAMREG_SAVE+40(%r29) 237 ld %r9,PARAMREG_SAVE+48(%r29) 238 addi %r0,%r12,12 # add 3 instructions 239 ld %r10,PARAMREG_SAVE+56(%r29) 240 ld %r11,STATIC_CHAIN_SAVE(%r29) 241 cmpld %cr7,%r12,%r0 # indicate we were called 242 mtctr %r0 243 bctrl # call caller! 244 245# On return, save regs possibly used to return a value, and 246# possibly trashed by calls to __morestack_block_signals, 247# __generic_releasestack and __morestack_unblock_signals. 248# Assume those calls don't use vector or floating point regs. 249 std %r3,PARAMREG_SAVE+0(%r29) 250 std %r4,PARAMREG_SAVE+8(%r29) 251 std %r5,PARAMREG_SAVE+16(%r29) 252 std %r6,PARAMREG_SAVE+24(%r29) 253#if _CALL_ELF == 2 254 std %r7,PARAMREG_SAVE+32(%r29) 255 std %r8,PARAMREG_SAVE+40(%r29) 256 std %r9,PARAMREG_SAVE+48(%r29) 257 std %r10,PARAMREG_SAVE+56(%r29) 258#endif 259 260#if _CALL_ELF == 2 && !defined __PCREL__ 261# r2 was restored for calling back into our caller. Set it up again. 262 bcl 20,31,1f 2631: 264 mflr %r12 265 addis %r2,%r12,.TOC.-1b@ha 266 addi %r2,%r2,.TOC.-1b@l 267#endif 268 269 bl JUMP_TARGET(__morestack_block_signals) 270 271 # void *__generic_releasestack (size_t *pavailable) 272 addi %r3,%r29,NEWSTACKSIZE_SAVE 273 bl JUMP_TARGET(__generic_releasestack) 274 275# Reset __private_ss stack guard to value for old stack 276 ld %r12,NEWSTACKSIZE_SAVE(%r29) 277 addi %r3,%r3,BACKOFF 278 sub %r3,%r3,%r12 279.LEHE0: 280 std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 281 282 bl JUMP_TARGET(__morestack_unblock_signals) 283 284# Use old stack again. 285 mr %r1,%r29 286 287# Restore return value regs, and return. 288 ld %r0,LINKREG_SAVE(%r29) 289 mtlr %r0 290#if _CALL_ELF == 2 291 ld %r2,R2_SAVE(%r29) 292#endif 293 ld %r3,PARAMREG_SAVE+0(%r29) 294 ld %r4,PARAMREG_SAVE+8(%r29) 295 ld %r5,PARAMREG_SAVE+16(%r29) 296 ld %r6,PARAMREG_SAVE+24(%r29) 297#if _CALL_ELF == 2 298 ld %r7,PARAMREG_SAVE+32(%r29) 299 ld %r8,PARAMREG_SAVE+40(%r29) 300 ld %r9,PARAMREG_SAVE+48(%r29) 301 ld %r10,PARAMREG_SAVE+56(%r29) 302#endif 303 ld %r29,R29_SAVE(%r29) 304 .cfi_def_cfa_register %r1 305 blr 306 307# This is the cleanup code called by the stack unwinder when 308# unwinding through code between .LEHB0 and .LEHE0 above. 309cleanup: 310 .cfi_def_cfa_register %r29 311 std %r3,PARAMREG_SAVE(%r29) # Save exception header 312 # size_t __generic_findstack (void *stack) 313 mr %r3,%r29 314 bl JUMP_TARGET(__generic_findstack) 315 sub %r3,%r29,%r3 316 addi %r3,%r3,BACKOFF 317 std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 318 ld %r3,PARAMREG_SAVE(%r29) 319 bl JUMP_TARGET(_Unwind_Resume) 320#ifndef __PCREL__ 321 nop 322#endif 323 .cfi_endproc 324 SIZE (__morestack) 325 326 327 .section .gcc_except_table,"a",@progbits 328 .p2align 2 329.LLSDA1: 330 .byte 0xff # @LPStart format (omit) 331 .byte 0xff # @TType format (omit) 332 .byte 0x1 # call-site format (uleb128) 333 .uleb128 .LLSDACSE1-.LLSDACSB1 # Call-site table length 334.LLSDACSB1: 335 .uleb128 .LEHB0-.LFB1 # region 0 start 336 .uleb128 .LEHE0-.LEHB0 # length 337 .uleb128 cleanup-.LFB1 # landing pad 338 .uleb128 0 # no action, ie. a cleanup 339.LLSDACSE1: 340 341 342#ifdef __PIC__ 343# Build a position independent reference to the personality function. 344 .hidden DW.ref.__gcc_personality_v0 345 .weak DW.ref.__gcc_personality_v0 346 .section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat 347 .p2align 3 348DW.ref.__gcc_personality_v0: 349 .quad __gcc_personality_v0 350 .type DW.ref.__gcc_personality_v0, @object 351 .size DW.ref.__gcc_personality_v0, 8 352#endif 353 354 355 .text 356# Initialize the stack guard when the program starts or when a 357# new thread starts. This is called from a constructor. 358# void __stack_split_initialize (void) 359ENTRY(__stack_split_initialize) 360 .cfi_startproc 361 addi %r3,%r1,-0x4000 # We should have at least 16K. 362 std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 363 # void __generic_morestack_set_initial_sp (void *sp, size_t len) 364 mr %r3,%r1 365 li %r4, 0x4000 366 b JUMP_TARGET(__generic_morestack_set_initial_sp) 367# The lack of .cfi_endproc here is deliberate. This function and the 368# following ones can all use the default FDE. 369 SIZE (__stack_split_initialize) 370 371 372# Return current __private_ss 373# void *__morestack_get_guard (void) 374ENTRY0(__morestack_get_guard) 375 ld %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 376 blr 377 SIZE (__morestack_get_guard) 378 379 380# Set __private_ss 381# void __morestack_set_guard (void *ptr) 382ENTRY0(__morestack_set_guard) 383 std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss 384 blr 385 SIZE (__morestack_set_guard) 386 387 388# Return the stack guard value for given stack 389# void *__morestack_make_guard (void *stack, size_t size) 390ENTRY0(__morestack_make_guard) 391 sub %r3,%r3,%r4 392 addi %r3,%r3,BACKOFF 393 blr 394 .cfi_endproc 395 SIZE (__morestack_make_guard) 396 397 398# Make __stack_split_initialize a high priority constructor. 399 .section .ctors.65535,"aw",@progbits 400 .p2align 3 401 .quad __stack_split_initialize 402 .quad __morestack_load_mmap 403 404 .section .note.GNU-stack,"",@progbits 405 .section .note.GNU-split-stack,"",@progbits 406 .section .note.GNU-no-split-stack,"",@progbits 407#endif /* __powerpc64__ */ 408