morestack.S 11 KB

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