1  /* PLT trampolines.  s390 version.
       2     Copyright (C) 2016-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  /* This code is used in dl-runtime.c to call the `fixup' function
      20     and then redirect to the address it returns.  */
      21  
      22  /* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
      23   * with the following linkage:
      24   *   r2 - r6 : parameter registers
      25   *   f0, f2 : floating point parameter registers
      26   *   v24, v26, v28, v30, v25, v27, v29, v31 : vector parameter registers
      27   *   24(r15), 28(r15) : PLT arguments PLT1, PLT2
      28   *   96(r15) : additional stack parameters
      29   * The slightly tightened normal clobber rules for function calls apply:
      30   *   r0 : call saved (for __fentry__)
      31   *   r1 - r5 : call clobbered
      32   *   r6 - r13 :	call saved
      33   *   r14 : return address (call clobbered)
      34   *   r15 : stack pointer (call saved)
      35   *   f4, f6 : call saved
      36   *   f0 - f3, f5, f7 - f15 : call clobbered
      37   *   v0 - v3, v5, v7 - v15 : bytes 0-7 overlap with fprs: call clobbered
      38                 bytes 8-15: call clobbered
      39   *   v4, v6 : bytes 0-7 overlap with f4, f6: call saved
      40                bytes 8-15: call clobbered
      41   *   v16 - v31 : call clobbered
      42   */
      43  
      44  #define CFA_OFF 96
      45  #define FRAME_OFF CFA_OFF + FRAME_SIZE
      46  #define V24_OFF -224
      47  #define V25_OFF -208
      48  #define V26_OFF -192
      49  #define V27_OFF -176
      50  #define V28_OFF -160
      51  #define V29_OFF -144
      52  #define V30_OFF -128
      53  #define V31_OFF -112
      54  #define R0_OFF -76
      55  #define PLT1_OFF -72
      56  #define PLT2_OFF -68
      57  #define R2_OFF -64
      58  #define R3_OFF -60
      59  #define R4_OFF -56
      60  #define R5_OFF -52
      61  #define R14_OFF -48
      62  #define R15_OFF -44
      63  #define F0_OFF -40
      64  #define F2_OFF -32
      65  	.globl _dl_runtime_resolve
      66  	.type _dl_runtime_resolve, @function
      67  	cfi_startproc
      68  	.align 16
      69  _dl_runtime_resolve:
      70  	st     %r0,CFA_OFF+R0_OFF(%r15)
      71  	cfi_offset (r0, R0_OFF)
      72  	stm    %r2,%r5,CFA_OFF+R2_OFF(%r15) # save registers
      73  	cfi_offset (r2, R2_OFF)
      74  	cfi_offset (r3, R3_OFF)
      75  	cfi_offset (r4, R4_OFF)
      76  	cfi_offset (r5, R5_OFF)
      77  	stm    %r14,%r15,CFA_OFF+R14_OFF(%r15)
      78  	cfi_offset (r14, R14_OFF)
      79  	cfi_offset (r15, R15_OFF)
      80  	std    %f0,CFA_OFF+F0_OFF(%r15)
      81  	cfi_offset (f0, F0_OFF)
      82  	std    %f2,CFA_OFF+F2_OFF(%r15)
      83  	cfi_offset (f2, F2_OFF)
      84  	lr     %r0,%r15
      85  	lm     %r2,%r3,CFA_OFF+PLT1_OFF(%r15) # load args saved by PLT
      86  #ifdef RESTORE_VRS
      87  # define FRAME_SIZE (CFA_OFF + 128)
      88  	ahi    %r15,-FRAME_SIZE # create stack frame
      89  	cfi_adjust_cfa_offset (FRAME_SIZE)
      90  	.machine push
      91  	.machine "z13"
      92  	.machinemode "zarch_nohighgprs"
      93  	vstm   %v24,%v31,FRAME_OFF+V24_OFF(%r15) # save call-clobbered vr args
      94  	cfi_offset (v24, V24_OFF)
      95  	cfi_offset (v25, V25_OFF)
      96  	cfi_offset (v26, V26_OFF)
      97  	cfi_offset (v27, V27_OFF)
      98  	cfi_offset (v28, V28_OFF)
      99  	cfi_offset (v29, V29_OFF)
     100  	cfi_offset (v30, V30_OFF)
     101  	cfi_offset (v31, V31_OFF)
     102  	.machine pop
     103  #else
     104  # define FRAME_SIZE CFA_OFF
     105  	ahi    %r15,-FRAME_SIZE # create stack frame
     106  	cfi_adjust_cfa_offset (FRAME_SIZE)
     107  #endif
     108  	st     %r0,0(%r15)		# write backchain
     109  	basr   %r1,0
     110  0:	l      %r14,1f-0b(%r1)
     111  	bas    %r14,0(%r14,%r1)		# call _dl_fixup
     112  	lr     %r1,%r2			# function addr returned in r2
     113  #ifdef RESTORE_VRS
     114  	.machine push
     115  	.machine "z13"
     116  	.machinemode "zarch_nohighgprs"
     117  	vlm    %v24,%v31,FRAME_OFF+V24_OFF(%r15) # restore vector registers
     118  	.machine pop
     119  #endif
     120  	lm     %r14,%r15,FRAME_OFF+R14_OFF(%r15) # restore frame and registers
     121  #undef FRAME_SIZE
     122  	cfi_def_cfa_offset (CFA_OFF)
     123  	ld     %f0,CFA_OFF+F0_OFF(%r15)
     124  	ld     %f2,CFA_OFF+F2_OFF(%r15)
     125  	lm     %r2,%r5,CFA_OFF+R2_OFF(%r15)
     126  	l      %r0,CFA_OFF+R0_OFF(%r15)
     127  	br     %r1
     128  1:	.long  _dl_fixup - 0b
     129  	cfi_endproc
     130  	.size _dl_runtime_resolve, .-_dl_runtime_resolve
     131  #undef V24_OFF
     132  #undef V25_OFF
     133  #undef V26_OFF
     134  #undef V27_OFF
     135  #undef V28_OFF
     136  #undef V29_OFF
     137  #undef V30_OFF
     138  #undef V31_OFF
     139  #undef R0_OFF
     140  #undef PLT1_OFF
     141  #undef PLT2_OFF
     142  #undef R2_OFF
     143  #undef R3_OFF
     144  #undef R4_OFF
     145  #undef R5_OFF
     146  #undef R14_OFF
     147  #undef R15_OFF
     148  #undef F0_OFF
     149  #undef F2_OFF
     150  
     151  #ifndef PROF
     152  # define SIZEOF_STRUCT_LA_S390_32_REGS 168
     153  # define REGS_OFF -264
     154  # define R2_OFF -264
     155  # define R3_OFF -260
     156  # define R4_OFF -256
     157  # define R5_OFF -252
     158  # define R6_OFF -248
     159  # define F0_OFF -240
     160  # define F2_OFF -232
     161  # define V24_OFF -224
     162  # define V25_OFF -208
     163  # define V26_OFF -192
     164  # define V27_OFF -176
     165  # define V28_OFF -160
     166  # define V29_OFF -144
     167  # define V30_OFF -128
     168  # define V31_OFF -112
     169  # define R0_OFF -88
     170  # define R12_OFF -84
     171  # define R14_OFF -80
     172  # define FRAMESIZE_OFF -76
     173  # define PLT1_OFF -72
     174  # define PLT2_OFF -68
     175  # define PREGS_OFF -64
     176  # define RETVAL_OFF -56
     177  # define RET_R2_OFF -56
     178  # define RET_R3_OFF -52
     179  # define RET_F0_OFF -48
     180  # define RET_V24_OFF -40
     181  	.globl _dl_runtime_profile
     182  	.type _dl_runtime_profile, @function
     183  	cfi_startproc
     184  	.align 16
     185  _dl_runtime_profile:
     186  	st     %r0,CFA_OFF+R0_OFF(%r15)
     187  	cfi_offset (r0, R0_OFF)
     188  	st     %r12,CFA_OFF+R12_OFF(%r15)	# r12 is used as backup of r15
     189  	cfi_offset (r12, R12_OFF)
     190  	st     %r14,CFA_OFF+R14_OFF(%r15)
     191  	cfi_offset (r14, R14_OFF)
     192  	lr     %r12,%r15			# backup stack pointer
     193  	cfi_def_cfa_register (12)
     194  # define FRAME_SIZE (CFA_OFF + SIZEOF_STRUCT_LA_S390_32_REGS)
     195  	ahi    %r15,-FRAME_SIZE			# create stack frame:
     196  	st     %r12,0(%r15)			# save backchain
     197  
     198  	stm    %r2,%r6,FRAME_OFF+R2_OFF(%r15)	# save registers
     199  	cfi_offset (r2, R2_OFF)			# + r6 needed as arg for
     200  	cfi_offset (r3, R3_OFF)			#  _dl_profile_fixup
     201  	cfi_offset (r4, R4_OFF)
     202  	cfi_offset (r5, R5_OFF)
     203  	cfi_offset (r6, R6_OFF)
     204  	std    %f0,FRAME_OFF+F0_OFF(%r15)
     205  	cfi_offset (f0, F0_OFF)
     206  	std    %f2,FRAME_OFF+F2_OFF(%r15)
     207  	cfi_offset (f2, F2_OFF)
     208  # ifdef RESTORE_VRS
     209  	.machine push
     210  	.machine "z13"
     211  	.machinemode "zarch_nohighgprs"
     212  	vstm   %v24,%v31,FRAME_OFF+V24_OFF(%r15)	# store call-clobbered
     213  	cfi_offset (v24, V24_OFF)			# vr arguments
     214  	cfi_offset (v25, V25_OFF)
     215  	cfi_offset (v26, V26_OFF)
     216  	cfi_offset (v27, V27_OFF)
     217  	cfi_offset (v28, V28_OFF)
     218  	cfi_offset (v29, V29_OFF)
     219  	cfi_offset (v30, V30_OFF)
     220  	cfi_offset (v31, V31_OFF)
     221  	.machine pop
     222  # endif
     223  
     224  	lm     %r2,%r3,CFA_OFF+PLT1_OFF(%r12)	# load arguments saved by PLT
     225  	lr     %r4,%r14				# return address as third parm
     226  	basr   %r1,0
     227  0:	l      %r14,6f-0b(%r1)
     228  	la     %r5,FRAME_OFF+REGS_OFF(%r15)	# struct La_s390_32_regs *
     229  	la     %r6,CFA_OFF+FRAMESIZE_OFF(%r12)	# long int * framesize
     230  	bas    %r14,0(%r14,%r1)			# call resolver
     231  	lr     %r1,%r2				# function addr returned in r2
     232  	ld     %f0,FRAME_OFF+F0_OFF(%r15)	# restore call-clobbered
     233  	ld     %f2,FRAME_OFF+F2_OFF(%r15)	# arg fprs
     234  # ifdef RESTORE_VRS
     235  	.machine push
     236  	.machine "z13"
     237  	.machinemode "zarch_nohighgprs"		# restore call-clobbered
     238  	vlm    %v24,%v31,FRAME_OFF+V24_OFF(%r15)# arg vrs
     239  	.machine pop
     240  # endif
     241  	icm    %r0,15,CFA_OFF+FRAMESIZE_OFF(%r12)	# load & test framesize
     242  	jnm    2f
     243  						# framesize < 0 means no
     244  	lm     %r2,%r6,FRAME_OFF+R2_OFF(%r15)	# pltexit call, so we can do a
     245  						# tail call without
     246  						# copying the arg overflow area
     247  	lr     %r15,%r12			# remove stack frame
     248  	cfi_def_cfa_register (15)
     249  	l      %r14,CFA_OFF+R14_OFF(%r15)	# restore registers
     250  	l      %r12,CFA_OFF+R12_OFF(%r15)
     251  	l      %r0,CFA_OFF+R0_OFF(%r15)
     252  	br     %r1				# tail call
     253  
     254  	cfi_def_cfa_register (12)
     255  2:	la     %r4,FRAME_OFF+REGS_OFF(%r15)	# struct La_s390_32_regs *
     256  	st     %r4,CFA_OFF+PREGS_OFF(%r12)
     257  	jz     4f				# framesize == 0 ?
     258  	ahi    %r0,7				# align framesize to 8
     259  	lhi    %r2,-8
     260  	nr     %r0,%r2
     261  	slr    %r15,%r0				# make room for framesize bytes
     262  	st     %r12,0(%r15)			# save backchain
     263  	la     %r2,FRAME_OFF+REGS_OFF(%r15)
     264  	la     %r3,CFA_OFF(%r12)
     265  	srl    %r0,3
     266  3:	mvc    0(8,%r2),0(%r3)			# copy additional parameters
     267  	la     %r2,8(%r2)
     268  	la     %r3,8(%r3)
     269  	brct   %r0,3b
     270  4:	lm     %r2,%r6,0(%r4)			# load register parameters
     271  	basr   %r14,%r1				# call resolved function
     272  	stm    %r2,%r3,CFA_OFF+RET_R2_OFF(%r12)	# store return vals r2, r3, f0
     273  	std    %f0,CFA_OFF+RET_F0_OFF(%r12)	# to struct La_s390_32_retval
     274  # ifdef RESTORE_VRS
     275  	.machine push
     276  	.machine "z13"
     277  	vst    %v24,CFA_OFF+RET_V24_OFF(%r12)	# store return value v24
     278  	.machine pop
     279  # endif
     280  	lm     %r2,%r4,CFA_OFF+PLT1_OFF(%r12)	# r2, r3: args saved by PLT
     281  						# r4: struct La_s390_32_regs *
     282  	basr   %r1,0
     283  5:	l      %r14,7f-5b(%r1)
     284  	la     %r5,CFA_OFF+RETVAL_OFF(%r12)	# struct La_s390_32_retval *
     285  	bas    %r14,0(%r14,%r1)			# call _dl_audit_pltexit
     286  
     287  	lr     %r15,%r12			# remove stack frame
     288  # undef FRAME_SIZE
     289  	cfi_def_cfa_register (15)
     290  	l      %r14,CFA_OFF+R14_OFF(%r15)	# restore registers
     291  	l      %r12,CFA_OFF+R12_OFF(%r15)
     292  	l      %r0,CFA_OFF+R0_OFF(%r15)
     293  	lm     %r2,%r3,CFA_OFF+RET_R2_OFF(%r15)	# restore return values
     294  	ld     %f0,CFA_OFF+RET_F0_OFF(%r15)
     295  # ifdef RESTORE_VRS
     296  	.machine push
     297  	.machine "z13"
     298  	vl    %v24,CFA_OFF+RET_V24_OFF(%r15)	# restore return value v24
     299  	.machine pop
     300  # endif
     301  	br     %r14
     302  
     303  6:	.long  _dl_profile_fixup - 0b
     304  7:	.long  _dl_audit_pltexit - 5b
     305  	cfi_endproc
     306  	.size _dl_runtime_profile, .-_dl_runtime_profile
     307  # undef SIZEOF_STRUCT_LA_S390_32_REGS
     308  # undef REGS_OFF
     309  # undef R2_OFF
     310  # undef R3_OFF
     311  # undef R4_OFF
     312  # undef R5_OFF
     313  # undef R6_OFF
     314  # undef F0_OFF
     315  # undef F2_OFF
     316  # undef V24_OFF
     317  # undef V25_OFF
     318  # undef V26_OFF
     319  # undef V27_OFF
     320  # undef V28_OFF
     321  # undef V29_OFF
     322  # undef V30_OFF
     323  # undef V31_OFF
     324  # undef R0_OFF
     325  # undef R12_OFF
     326  # undef R14_OFF
     327  # undef FRAMESIZE_OFF
     328  # undef PLT1_OFF
     329  # undef PLT2_OFF
     330  # undef PREGS_OFF
     331  # undef RETVAL_OFF
     332  # undef RET_R2_OFF
     333  # undef RET_R3_OFF
     334  # undef RET_F0_OFF
     335  # undef RET_V24_OFF
     336  #endif