Blame sysdeps/x86_64/dl-trampoline.h

Packit 6c4009
/* PLT trampolines.  x86-64 version.
Packit 6c4009
   Copyright (C) 2009-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
	.text
Packit 6c4009
#ifdef _dl_runtime_resolve
Packit 6c4009
Packit 6c4009
# undef REGISTER_SAVE_AREA
Packit 6c4009
# undef LOCAL_STORAGE_AREA
Packit 6c4009
# undef BASE
Packit 6c4009
Packit 6c4009
# if (STATE_SAVE_ALIGNMENT % 16) != 0
Packit 6c4009
#  error STATE_SAVE_ALIGNMENT must be multples of 16
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
# if (STATE_SAVE_OFFSET % STATE_SAVE_ALIGNMENT) != 0
Packit 6c4009
#  error STATE_SAVE_OFFSET must be multples of STATE_SAVE_ALIGNMENT
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
# if DL_RUNTIME_RESOLVE_REALIGN_STACK
Packit 6c4009
/* Local stack area before jumping to function address: RBX.  */
Packit 6c4009
#  define LOCAL_STORAGE_AREA	8
Packit 6c4009
#  define BASE			rbx
Packit 6c4009
#  ifdef USE_FXSAVE
Packit 6c4009
/* Use fxsave to save XMM registers.  */
Packit 6c4009
#   define REGISTER_SAVE_AREA	(512 + STATE_SAVE_OFFSET)
Packit 6c4009
#   if (REGISTER_SAVE_AREA % 16) != 0
Packit 6c4009
#    error REGISTER_SAVE_AREA must be multples of 16
Packit 6c4009
#   endif
Packit 6c4009
#  endif
Packit 6c4009
# else
Packit 6c4009
#  ifndef USE_FXSAVE
Packit 6c4009
#   error USE_FXSAVE must be defined
Packit 6c4009
#  endif
Packit 6c4009
/* Use fxsave to save XMM registers.  */
Packit 6c4009
#  define REGISTER_SAVE_AREA	(512 + STATE_SAVE_OFFSET + 8)
Packit 6c4009
/* Local stack area before jumping to function address:  All saved
Packit 6c4009
   registers.  */
Packit 6c4009
#  define LOCAL_STORAGE_AREA	REGISTER_SAVE_AREA
Packit 6c4009
#  define BASE			rsp
Packit 6c4009
#  if (REGISTER_SAVE_AREA % 16) != 8
Packit 6c4009
#   error REGISTER_SAVE_AREA must be odd multples of 8
Packit 6c4009
#  endif
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
	.globl _dl_runtime_resolve
Packit 6c4009
	.hidden _dl_runtime_resolve
Packit 6c4009
	.type _dl_runtime_resolve, @function
Packit 6c4009
	.align 16
Packit 6c4009
	cfi_startproc
Packit 6c4009
_dl_runtime_resolve:
Packit 6c4009
	cfi_adjust_cfa_offset(16) # Incorporate PLT
Packit 6c4009
	_CET_ENDBR
Packit 6c4009
# if DL_RUNTIME_RESOLVE_REALIGN_STACK
Packit 6c4009
#  if LOCAL_STORAGE_AREA != 8
Packit 6c4009
#   error LOCAL_STORAGE_AREA must be 8
Packit 6c4009
#  endif
Packit 6c4009
	pushq %rbx			# push subtracts stack by 8.
Packit 6c4009
	cfi_adjust_cfa_offset(8)
Packit 6c4009
	cfi_rel_offset(%rbx, 0)
Packit 6c4009
	mov %RSP_LP, %RBX_LP
Packit 6c4009
	cfi_def_cfa_register(%rbx)
Packit 6c4009
	and $-STATE_SAVE_ALIGNMENT, %RSP_LP
Packit 6c4009
# endif
Packit 6c4009
# ifdef REGISTER_SAVE_AREA
Packit 6c4009
	sub $REGISTER_SAVE_AREA, %RSP_LP
Packit 6c4009
#  if !DL_RUNTIME_RESOLVE_REALIGN_STACK
Packit 6c4009
	cfi_adjust_cfa_offset(REGISTER_SAVE_AREA)
Packit 6c4009
#  endif
Packit 6c4009
# else
Packit 6c4009
	# Allocate stack space of the required size to save the state.
Packit 6c4009
#  if IS_IN (rtld)
Packit 6c4009
	sub _rtld_local_ro+RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET+XSAVE_STATE_SIZE_OFFSET(%rip), %RSP_LP
Packit 6c4009
#  else
Packit 6c4009
	sub _dl_x86_cpu_features+XSAVE_STATE_SIZE_OFFSET(%rip), %RSP_LP
Packit 6c4009
#  endif
Packit 6c4009
# endif
Packit 6c4009
	# Preserve registers otherwise clobbered.
Packit 6c4009
	movq %rax, REGISTER_SAVE_RAX(%rsp)
Packit 6c4009
	movq %rcx, REGISTER_SAVE_RCX(%rsp)
Packit 6c4009
	movq %rdx, REGISTER_SAVE_RDX(%rsp)
Packit 6c4009
	movq %rsi, REGISTER_SAVE_RSI(%rsp)
Packit 6c4009
	movq %rdi, REGISTER_SAVE_RDI(%rsp)
Packit 6c4009
	movq %r8, REGISTER_SAVE_R8(%rsp)
Packit 6c4009
	movq %r9, REGISTER_SAVE_R9(%rsp)
Packit 6c4009
# ifdef USE_FXSAVE
Packit 6c4009
	fxsave STATE_SAVE_OFFSET(%rsp)
Packit 6c4009
# else
Packit 6c4009
	movl $STATE_SAVE_MASK, %eax
Packit 6c4009
	xorl %edx, %edx
Packit 6c4009
	# Clear the XSAVE Header.
Packit 6c4009
#  ifdef USE_XSAVE
Packit 6c4009
	movq %rdx, (STATE_SAVE_OFFSET + 512)(%rsp)
Packit 6c4009
	movq %rdx, (STATE_SAVE_OFFSET + 512 + 8)(%rsp)
Packit 6c4009
#  endif
Packit 6c4009
	movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 2)(%rsp)
Packit 6c4009
	movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 3)(%rsp)
Packit 6c4009
	movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 4)(%rsp)
Packit 6c4009
	movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 5)(%rsp)
Packit 6c4009
	movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 6)(%rsp)
Packit 6c4009
	movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 7)(%rsp)
Packit 6c4009
#  ifdef USE_XSAVE
Packit 6c4009
	xsave STATE_SAVE_OFFSET(%rsp)
Packit 6c4009
#  else
Packit 6c4009
	xsavec STATE_SAVE_OFFSET(%rsp)
Packit 6c4009
#  endif
Packit 6c4009
# endif
Packit 6c4009
	# Copy args pushed by PLT in register.
Packit 6c4009
	# %rdi: link_map, %rsi: reloc_index
Packit 6c4009
	mov (LOCAL_STORAGE_AREA + 8)(%BASE), %RSI_LP
Packit 6c4009
	mov LOCAL_STORAGE_AREA(%BASE), %RDI_LP
Packit 6c4009
	call _dl_fixup		# Call resolver.
Packit 6c4009
	mov %RAX_LP, %R11_LP	# Save return value
Packit 6c4009
	# Get register content back.
Packit 6c4009
# ifdef USE_FXSAVE
Packit 6c4009
	fxrstor STATE_SAVE_OFFSET(%rsp)
Packit 6c4009
# else
Packit 6c4009
	movl $STATE_SAVE_MASK, %eax
Packit 6c4009
	xorl %edx, %edx
Packit 6c4009
	xrstor STATE_SAVE_OFFSET(%rsp)
Packit 6c4009
# endif
Packit 6c4009
	movq REGISTER_SAVE_R9(%rsp), %r9
Packit 6c4009
	movq REGISTER_SAVE_R8(%rsp), %r8
Packit 6c4009
	movq REGISTER_SAVE_RDI(%rsp), %rdi
Packit 6c4009
	movq REGISTER_SAVE_RSI(%rsp), %rsi
Packit 6c4009
	movq REGISTER_SAVE_RDX(%rsp), %rdx
Packit 6c4009
	movq REGISTER_SAVE_RCX(%rsp), %rcx
Packit 6c4009
	movq REGISTER_SAVE_RAX(%rsp), %rax
Packit 6c4009
# if DL_RUNTIME_RESOLVE_REALIGN_STACK
Packit 6c4009
	mov %RBX_LP, %RSP_LP
Packit 6c4009
	cfi_def_cfa_register(%rsp)
Packit 6c4009
	movq (%rsp), %rbx
Packit 6c4009
	cfi_restore(%rbx)
Packit 6c4009
# endif
Packit 6c4009
	# Adjust stack(PLT did 2 pushes)
Packit 6c4009
	add $(LOCAL_STORAGE_AREA + 16), %RSP_LP
Packit 6c4009
	cfi_adjust_cfa_offset(-(LOCAL_STORAGE_AREA + 16))
Packit 6c4009
	# Preserve bound registers.
Packit 6c4009
	PRESERVE_BND_REGS_PREFIX
Packit 6c4009
	jmp *%r11		# Jump to function address.
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size _dl_runtime_resolve, .-_dl_runtime_resolve
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
Packit 6c4009
#if !defined PROF && defined _dl_runtime_profile
Packit 6c4009
# if (LR_VECTOR_OFFSET % VEC_SIZE) != 0
Packit 6c4009
#  error LR_VECTOR_OFFSET must be multples of VEC_SIZE
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
	.globl _dl_runtime_profile
Packit 6c4009
	.hidden _dl_runtime_profile
Packit 6c4009
	.type _dl_runtime_profile, @function
Packit 6c4009
	.align 16
Packit 6c4009
_dl_runtime_profile:
Packit 6c4009
	cfi_startproc
Packit 6c4009
	cfi_adjust_cfa_offset(16) # Incorporate PLT
Packit 6c4009
	_CET_ENDBR
Packit 6c4009
	/* The La_x86_64_regs data structure pointed to by the
Packit 6c4009
	   fourth paramater must be VEC_SIZE-byte aligned.  This must
Packit 6c4009
	   be explicitly enforced.  We have the set up a dynamically
Packit 6c4009
	   sized stack frame.  %rbx points to the top half which
Packit 6c4009
	   has a fixed size and preserves the original stack pointer.  */
Packit 6c4009
Packit 6c4009
	sub $32, %RSP_LP	# Allocate the local storage.
Packit 6c4009
	cfi_adjust_cfa_offset(32)
Packit 6c4009
	movq %rbx, (%rsp)
Packit 6c4009
	cfi_rel_offset(%rbx, 0)
Packit 6c4009
Packit 6c4009
	/* On the stack:
Packit 6c4009
		56(%rbx)	parameter #1
Packit 6c4009
		48(%rbx)	return address
Packit 6c4009
Packit 6c4009
		40(%rbx)	reloc index
Packit 6c4009
		32(%rbx)	link_map
Packit 6c4009
Packit 6c4009
		24(%rbx)	La_x86_64_regs pointer
Packit 6c4009
		16(%rbx)	framesize
Packit 6c4009
		 8(%rbx)	rax
Packit 6c4009
		  (%rbx)	rbx
Packit 6c4009
	*/
Packit 6c4009
Packit 6c4009
	movq %rax, 8(%rsp)
Packit 6c4009
	mov %RSP_LP, %RBX_LP
Packit 6c4009
	cfi_def_cfa_register(%rbx)
Packit 6c4009
Packit 6c4009
	/* Actively align the La_x86_64_regs structure.  */
Packit 6c4009
	and $-VEC_SIZE, %RSP_LP
Packit 6c4009
	/* sizeof(La_x86_64_regs).  Need extra space for 8 SSE registers
Packit 6c4009
	   to detect if any xmm0-xmm7 registers are changed by audit
Packit 6c4009
	   module.  */
Packit 6c4009
	sub $(LR_SIZE + XMM_SIZE*8), %RSP_LP
Packit 6c4009
	movq %rsp, 24(%rbx)
Packit 6c4009
Packit 6c4009
	/* Fill the La_x86_64_regs structure.  */
Packit 6c4009
	movq %rdx, LR_RDX_OFFSET(%rsp)
Packit 6c4009
	movq %r8,  LR_R8_OFFSET(%rsp)
Packit 6c4009
	movq %r9,  LR_R9_OFFSET(%rsp)
Packit 6c4009
	movq %rcx, LR_RCX_OFFSET(%rsp)
Packit 6c4009
	movq %rsi, LR_RSI_OFFSET(%rsp)
Packit 6c4009
	movq %rdi, LR_RDI_OFFSET(%rsp)
Packit 6c4009
	movq %rbp, LR_RBP_OFFSET(%rsp)
Packit 6c4009
Packit 6c4009
	lea 48(%rbx), %RAX_LP
Packit 6c4009
	movq %rax, LR_RSP_OFFSET(%rsp)
Packit 6c4009
Packit 6c4009
	/* We always store the XMM registers even if AVX is available.
Packit 6c4009
	   This is to provide backward binary compatibility for existing
Packit 6c4009
	   audit modules.  */
Packit 6c4009
	movaps %xmm0,		   (LR_XMM_OFFSET)(%rsp)
Packit 6c4009
	movaps %xmm1, (LR_XMM_OFFSET +   XMM_SIZE)(%rsp)
Packit 6c4009
	movaps %xmm2, (LR_XMM_OFFSET + XMM_SIZE*2)(%rsp)
Packit 6c4009
	movaps %xmm3, (LR_XMM_OFFSET + XMM_SIZE*3)(%rsp)
Packit 6c4009
	movaps %xmm4, (LR_XMM_OFFSET + XMM_SIZE*4)(%rsp)
Packit 6c4009
	movaps %xmm5, (LR_XMM_OFFSET + XMM_SIZE*5)(%rsp)
Packit 6c4009
	movaps %xmm6, (LR_XMM_OFFSET + XMM_SIZE*6)(%rsp)
Packit 6c4009
	movaps %xmm7, (LR_XMM_OFFSET + XMM_SIZE*7)(%rsp)
Packit 6c4009
Packit 6c4009
# ifndef __ILP32__
Packit 6c4009
#  ifdef HAVE_MPX_SUPPORT
Packit 6c4009
	bndmov %bnd0, 		   (LR_BND_OFFSET)(%rsp)  # Preserve bound
Packit 6c4009
	bndmov %bnd1, (LR_BND_OFFSET +   BND_SIZE)(%rsp)  # registers. Nops if
Packit 6c4009
	bndmov %bnd2, (LR_BND_OFFSET + BND_SIZE*2)(%rsp)  # MPX not available
Packit 6c4009
	bndmov %bnd3, (LR_BND_OFFSET + BND_SIZE*3)(%rsp)  # or disabled.
Packit 6c4009
#  else
Packit 6c4009
	.byte 0x66,0x0f,0x1b,0x84,0x24;.long (LR_BND_OFFSET)
Packit 6c4009
	.byte 0x66,0x0f,0x1b,0x8c,0x24;.long (LR_BND_OFFSET + BND_SIZE)
Packit 6c4009
	.byte 0x66,0x0f,0x1b,0x94,0x24;.long (LR_BND_OFFSET + BND_SIZE*2)
Packit 6c4009
	.byte 0x66,0x0f,0x1b,0x9c,0x24;.long (LR_BND_OFFSET + BND_SIZE*3)
Packit 6c4009
#  endif
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
# ifdef RESTORE_AVX
Packit 6c4009
	/* This is to support AVX audit modules.  */
Packit 6c4009
	VMOVA %VEC(0),		      (LR_VECTOR_OFFSET)(%rsp)
Packit 6c4009
	VMOVA %VEC(1), (LR_VECTOR_OFFSET +   VECTOR_SIZE)(%rsp)
Packit 6c4009
	VMOVA %VEC(2), (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp)
Packit 6c4009
	VMOVA %VEC(3), (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp)
Packit 6c4009
	VMOVA %VEC(4), (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp)
Packit 6c4009
	VMOVA %VEC(5), (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp)
Packit 6c4009
	VMOVA %VEC(6), (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp)
Packit 6c4009
	VMOVA %VEC(7), (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp)
Packit 6c4009
Packit 6c4009
	/* Save xmm0-xmm7 registers to detect if any of them are
Packit 6c4009
	   changed by audit module.  */
Packit 6c4009
	vmovdqa %xmm0,		    (LR_SIZE)(%rsp)
Packit 6c4009
	vmovdqa %xmm1, (LR_SIZE +   XMM_SIZE)(%rsp)
Packit 6c4009
	vmovdqa %xmm2, (LR_SIZE + XMM_SIZE*2)(%rsp)
Packit 6c4009
	vmovdqa %xmm3, (LR_SIZE + XMM_SIZE*3)(%rsp)
Packit 6c4009
	vmovdqa %xmm4, (LR_SIZE + XMM_SIZE*4)(%rsp)
Packit 6c4009
	vmovdqa %xmm5, (LR_SIZE + XMM_SIZE*5)(%rsp)
Packit 6c4009
	vmovdqa %xmm6, (LR_SIZE + XMM_SIZE*6)(%rsp)
Packit 6c4009
	vmovdqa %xmm7, (LR_SIZE + XMM_SIZE*7)(%rsp)
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
	mov %RSP_LP, %RCX_LP	# La_x86_64_regs pointer to %rcx.
Packit 6c4009
	mov 48(%rbx), %RDX_LP	# Load return address if needed.
Packit 6c4009
	mov 40(%rbx), %RSI_LP	# Copy args pushed by PLT in register.
Packit 6c4009
	mov 32(%rbx), %RDI_LP	# %rdi: link_map, %rsi: reloc_index
Packit 6c4009
	lea 16(%rbx), %R8_LP	# Address of framesize
Packit 6c4009
	call _dl_profile_fixup	# Call resolver.
Packit 6c4009
Packit 6c4009
	mov %RAX_LP, %R11_LP	# Save return value.
Packit 6c4009
Packit 6c4009
	movq 8(%rbx), %rax	# Get back register content.
Packit 6c4009
	movq LR_RDX_OFFSET(%rsp), %rdx
Packit 6c4009
	movq  LR_R8_OFFSET(%rsp), %r8
Packit 6c4009
	movq  LR_R9_OFFSET(%rsp), %r9
Packit 6c4009
Packit 6c4009
	movaps		    (LR_XMM_OFFSET)(%rsp), %xmm0
Packit 6c4009
	movaps	 (LR_XMM_OFFSET + XMM_SIZE)(%rsp), %xmm1
Packit 6c4009
	movaps (LR_XMM_OFFSET + XMM_SIZE*2)(%rsp), %xmm2
Packit 6c4009
	movaps (LR_XMM_OFFSET + XMM_SIZE*3)(%rsp), %xmm3
Packit 6c4009
	movaps (LR_XMM_OFFSET + XMM_SIZE*4)(%rsp), %xmm4
Packit 6c4009
	movaps (LR_XMM_OFFSET + XMM_SIZE*5)(%rsp), %xmm5
Packit 6c4009
	movaps (LR_XMM_OFFSET + XMM_SIZE*6)(%rsp), %xmm6
Packit 6c4009
	movaps (LR_XMM_OFFSET + XMM_SIZE*7)(%rsp), %xmm7
Packit 6c4009
Packit 6c4009
# ifdef RESTORE_AVX
Packit 6c4009
	/* Check if any xmm0-xmm7 registers are changed by audit
Packit 6c4009
	   module.  */
Packit 6c4009
	vpcmpeqq (LR_SIZE)(%rsp), %xmm0, %xmm8
Packit 6c4009
	vpmovmskb %xmm8, %esi
Packit 6c4009
	cmpl $0xffff, %esi
Packit 6c4009
	je 2f
Packit 6c4009
	vmovdqa	%xmm0, (LR_VECTOR_OFFSET)(%rsp)
Packit 6c4009
	jmp 1f
Packit 6c4009
2:	VMOVA (LR_VECTOR_OFFSET)(%rsp), %VEC(0)
Packit 6c4009
	vmovdqa	%xmm0, (LR_XMM_OFFSET)(%rsp)
Packit 6c4009
Packit 6c4009
1:	vpcmpeqq (LR_SIZE + XMM_SIZE)(%rsp), %xmm1, %xmm8
Packit 6c4009
	vpmovmskb %xmm8, %esi
Packit 6c4009
	cmpl $0xffff, %esi
Packit 6c4009
	je 2f
Packit 6c4009
	vmovdqa	%xmm1, (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp)
Packit 6c4009
	jmp 1f
Packit 6c4009
2:	VMOVA (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp), %VEC(1)
Packit 6c4009
	vmovdqa	%xmm1, (LR_XMM_OFFSET + XMM_SIZE)(%rsp)
Packit 6c4009
Packit 6c4009
1:	vpcmpeqq (LR_SIZE + XMM_SIZE*2)(%rsp), %xmm2, %xmm8
Packit 6c4009
	vpmovmskb %xmm8, %esi
Packit 6c4009
	cmpl $0xffff, %esi
Packit 6c4009
	je 2f
Packit 6c4009
	vmovdqa	%xmm2, (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp)
Packit 6c4009
	jmp 1f
Packit 6c4009
2:	VMOVA (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp), %VEC(2)
Packit 6c4009
	vmovdqa	%xmm2, (LR_XMM_OFFSET + XMM_SIZE*2)(%rsp)
Packit 6c4009
Packit 6c4009
1:	vpcmpeqq (LR_SIZE + XMM_SIZE*3)(%rsp), %xmm3, %xmm8
Packit 6c4009
	vpmovmskb %xmm8, %esi
Packit 6c4009
	cmpl $0xffff, %esi
Packit 6c4009
	je 2f
Packit 6c4009
	vmovdqa	%xmm3, (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp)
Packit 6c4009
	jmp 1f
Packit 6c4009
2:	VMOVA (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp), %VEC(3)
Packit 6c4009
	vmovdqa	%xmm3, (LR_XMM_OFFSET + XMM_SIZE*3)(%rsp)
Packit 6c4009
Packit 6c4009
1:	vpcmpeqq (LR_SIZE + XMM_SIZE*4)(%rsp), %xmm4, %xmm8
Packit 6c4009
	vpmovmskb %xmm8, %esi
Packit 6c4009
	cmpl $0xffff, %esi
Packit 6c4009
	je 2f
Packit 6c4009
	vmovdqa	%xmm4, (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp)
Packit 6c4009
	jmp 1f
Packit 6c4009
2:	VMOVA (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp), %VEC(4)
Packit 6c4009
	vmovdqa	%xmm4, (LR_XMM_OFFSET + XMM_SIZE*4)(%rsp)
Packit 6c4009
Packit 6c4009
1:	vpcmpeqq (LR_SIZE + XMM_SIZE*5)(%rsp), %xmm5, %xmm8
Packit 6c4009
	vpmovmskb %xmm8, %esi
Packit 6c4009
	cmpl $0xffff, %esi
Packit 6c4009
	je 2f
Packit 6c4009
	vmovdqa	%xmm5, (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp)
Packit 6c4009
	jmp 1f
Packit 6c4009
2:	VMOVA (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp), %VEC(5)
Packit 6c4009
	vmovdqa	%xmm5, (LR_XMM_OFFSET + XMM_SIZE*5)(%rsp)
Packit 6c4009
Packit 6c4009
1:	vpcmpeqq (LR_SIZE + XMM_SIZE*6)(%rsp), %xmm6, %xmm8
Packit 6c4009
	vpmovmskb %xmm8, %esi
Packit 6c4009
	cmpl $0xffff, %esi
Packit 6c4009
	je 2f
Packit 6c4009
	vmovdqa	%xmm6, (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp)
Packit 6c4009
	jmp 1f
Packit 6c4009
2:	VMOVA (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp), %VEC(6)
Packit 6c4009
	vmovdqa	%xmm6, (LR_XMM_OFFSET + XMM_SIZE*6)(%rsp)
Packit 6c4009
Packit 6c4009
1:	vpcmpeqq (LR_SIZE + XMM_SIZE*7)(%rsp), %xmm7, %xmm8
Packit 6c4009
	vpmovmskb %xmm8, %esi
Packit 6c4009
	cmpl $0xffff, %esi
Packit 6c4009
	je 2f
Packit 6c4009
	vmovdqa	%xmm7, (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp)
Packit 6c4009
	jmp 1f
Packit 6c4009
2:	VMOVA (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp), %VEC(7)
Packit 6c4009
	vmovdqa	%xmm7, (LR_XMM_OFFSET + XMM_SIZE*7)(%rsp)
Packit 6c4009
Packit 6c4009
1:
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
# ifndef __ILP32__
Packit 6c4009
#  ifdef HAVE_MPX_SUPPORT
Packit 6c4009
	bndmov              (LR_BND_OFFSET)(%rsp), %bnd0  # Restore bound
Packit 6c4009
	bndmov (LR_BND_OFFSET +   BND_SIZE)(%rsp), %bnd1  # registers.
Packit 6c4009
	bndmov (LR_BND_OFFSET + BND_SIZE*2)(%rsp), %bnd2
Packit 6c4009
	bndmov (LR_BND_OFFSET + BND_SIZE*3)(%rsp), %bnd3
Packit 6c4009
#  else
Packit 6c4009
	.byte 0x66,0x0f,0x1a,0x84,0x24;.long (LR_BND_OFFSET)
Packit 6c4009
	.byte 0x66,0x0f,0x1a,0x8c,0x24;.long (LR_BND_OFFSET + BND_SIZE)
Packit 6c4009
	.byte 0x66,0x0f,0x1a,0x94,0x24;.long (LR_BND_OFFSET + BND_SIZE*2)
Packit 6c4009
	.byte 0x66,0x0f,0x1a,0x9c,0x24;.long (LR_BND_OFFSET + BND_SIZE*3)
Packit 6c4009
#  endif
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
	mov  16(%rbx), %R10_LP	# Anything in framesize?
Packit 6c4009
	test %R10_LP, %R10_LP
Packit 6c4009
	PRESERVE_BND_REGS_PREFIX
Packit 6c4009
	jns 3f
Packit 6c4009
Packit 6c4009
	/* There's nothing in the frame size, so there
Packit 6c4009
	   will be no call to the _dl_call_pltexit. */
Packit 6c4009
Packit 6c4009
	/* Get back registers content.  */
Packit 6c4009
	movq LR_RCX_OFFSET(%rsp), %rcx
Packit 6c4009
	movq LR_RSI_OFFSET(%rsp), %rsi
Packit 6c4009
	movq LR_RDI_OFFSET(%rsp), %rdi
Packit 6c4009
Packit 6c4009
	mov %RBX_LP, %RSP_LP
Packit 6c4009
	movq (%rsp), %rbx
Packit 6c4009
	cfi_restore(%rbx)
Packit 6c4009
	cfi_def_cfa_register(%rsp)
Packit 6c4009
Packit 6c4009
	add $48, %RSP_LP	# Adjust the stack to the return value
Packit 6c4009
				# (eats the reloc index and link_map)
Packit 6c4009
	cfi_adjust_cfa_offset(-48)
Packit 6c4009
	PRESERVE_BND_REGS_PREFIX
Packit 6c4009
	jmp *%r11		# Jump to function address.
Packit 6c4009
Packit 6c4009
3:
Packit 6c4009
	cfi_adjust_cfa_offset(48)
Packit 6c4009
	cfi_rel_offset(%rbx, 0)
Packit 6c4009
	cfi_def_cfa_register(%rbx)
Packit 6c4009
Packit 6c4009
	/* At this point we need to prepare new stack for the function
Packit 6c4009
	   which has to be called.  We copy the original stack to a
Packit 6c4009
	   temporary buffer of the size specified by the 'framesize'
Packit 6c4009
	   returned from _dl_profile_fixup */
Packit 6c4009
Packit 6c4009
	lea LR_RSP_OFFSET(%rbx), %RSI_LP # stack
Packit 6c4009
	add $8, %R10_LP
Packit 6c4009
	and $-16, %R10_LP
Packit 6c4009
	mov %R10_LP, %RCX_LP
Packit 6c4009
	sub %R10_LP, %RSP_LP
Packit 6c4009
	mov %RSP_LP, %RDI_LP
Packit 6c4009
	shr $3, %RCX_LP
Packit 6c4009
	rep
Packit 6c4009
	movsq
Packit 6c4009
Packit 6c4009
	movq 24(%rdi), %rcx	# Get back register content.
Packit 6c4009
	movq 32(%rdi), %rsi
Packit 6c4009
	movq 40(%rdi), %rdi
Packit 6c4009
Packit 6c4009
	PRESERVE_BND_REGS_PREFIX
Packit 6c4009
	call *%r11
Packit 6c4009
Packit 6c4009
	mov 24(%rbx), %RSP_LP	# Drop the copied stack content
Packit 6c4009
Packit 6c4009
	/* Now we have to prepare the La_x86_64_retval structure for the
Packit 6c4009
	   _dl_call_pltexit.  The La_x86_64_regs is being pointed by rsp now,
Packit 6c4009
	   so we just need to allocate the sizeof(La_x86_64_retval) space on
Packit 6c4009
	   the stack, since the alignment has already been taken care of. */
Packit 6c4009
# ifdef RESTORE_AVX
Packit 6c4009
	/* sizeof(La_x86_64_retval).  Need extra space for 2 SSE
Packit 6c4009
	   registers to detect if xmm0/xmm1 registers are changed
Packit 6c4009
	   by audit module.  Since rsp is aligned to VEC_SIZE, we
Packit 6c4009
	   need to make sure that the address of La_x86_64_retval +
Packit 6c4009
	   LRV_VECTOR0_OFFSET is aligned to VEC_SIZE.  */
Packit 6c4009
#  define LRV_SPACE (LRV_SIZE + XMM_SIZE*2)
Packit 6c4009
#  define LRV_MISALIGNED ((LRV_SIZE + LRV_VECTOR0_OFFSET) & (VEC_SIZE - 1))
Packit 6c4009
#  if LRV_MISALIGNED == 0
Packit 6c4009
	sub $LRV_SPACE, %RSP_LP
Packit 6c4009
#  else
Packit 6c4009
	sub $(LRV_SPACE + VEC_SIZE - LRV_MISALIGNED), %RSP_LP
Packit 6c4009
#  endif
Packit 6c4009
# else
Packit 6c4009
	sub $LRV_SIZE, %RSP_LP	# sizeof(La_x86_64_retval)
Packit 6c4009
# endif
Packit 6c4009
	mov %RSP_LP, %RCX_LP	# La_x86_64_retval argument to %rcx.
Packit 6c4009
Packit 6c4009
	/* Fill in the La_x86_64_retval structure.  */
Packit 6c4009
	movq %rax, LRV_RAX_OFFSET(%rcx)
Packit 6c4009
	movq %rdx, LRV_RDX_OFFSET(%rcx)
Packit 6c4009
Packit 6c4009
	movaps %xmm0, LRV_XMM0_OFFSET(%rcx)
Packit 6c4009
	movaps %xmm1, LRV_XMM1_OFFSET(%rcx)
Packit 6c4009
Packit 6c4009
# ifdef RESTORE_AVX
Packit 6c4009
	/* This is to support AVX audit modules.  */
Packit 6c4009
	VMOVA %VEC(0), LRV_VECTOR0_OFFSET(%rcx)
Packit 6c4009
	VMOVA %VEC(1), LRV_VECTOR1_OFFSET(%rcx)
Packit 6c4009
Packit 6c4009
	/* Save xmm0/xmm1 registers to detect if they are changed
Packit 6c4009
	   by audit module.  */
Packit 6c4009
	vmovdqa %xmm0,		  (LRV_SIZE)(%rcx)
Packit 6c4009
	vmovdqa %xmm1, (LRV_SIZE + XMM_SIZE)(%rcx)
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
# ifndef __ILP32__
Packit 6c4009
#  ifdef HAVE_MPX_SUPPORT
Packit 6c4009
	bndmov %bnd0, LRV_BND0_OFFSET(%rcx)  # Preserve returned bounds.
Packit 6c4009
	bndmov %bnd1, LRV_BND1_OFFSET(%rcx)
Packit 6c4009
#  else
Packit 6c4009
	.byte  0x66,0x0f,0x1b,0x81;.long (LRV_BND0_OFFSET)
Packit 6c4009
	.byte  0x66,0x0f,0x1b,0x89;.long (LRV_BND1_OFFSET)
Packit 6c4009
#  endif
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
	fstpt LRV_ST0_OFFSET(%rcx)
Packit 6c4009
	fstpt LRV_ST1_OFFSET(%rcx)
Packit 6c4009
Packit 6c4009
	movq 24(%rbx), %rdx	# La_x86_64_regs argument to %rdx.
Packit 6c4009
	movq 40(%rbx), %rsi	# Copy args pushed by PLT in register.
Packit 6c4009
	movq 32(%rbx), %rdi	# %rdi: link_map, %rsi: reloc_index
Packit 6c4009
	call _dl_call_pltexit
Packit 6c4009
Packit 6c4009
	/* Restore return registers.  */
Packit 6c4009
	movq LRV_RAX_OFFSET(%rsp), %rax
Packit 6c4009
	movq LRV_RDX_OFFSET(%rsp), %rdx
Packit 6c4009
Packit 6c4009
	movaps LRV_XMM0_OFFSET(%rsp), %xmm0
Packit 6c4009
	movaps LRV_XMM1_OFFSET(%rsp), %xmm1
Packit 6c4009
Packit 6c4009
# ifdef RESTORE_AVX
Packit 6c4009
	/* Check if xmm0/xmm1 registers are changed by audit module.  */
Packit 6c4009
	vpcmpeqq (LRV_SIZE)(%rsp), %xmm0, %xmm2
Packit 6c4009
	vpmovmskb %xmm2, %esi
Packit 6c4009
	cmpl $0xffff, %esi
Packit 6c4009
	jne 1f
Packit 6c4009
	VMOVA LRV_VECTOR0_OFFSET(%rsp), %VEC(0)
Packit 6c4009
Packit 6c4009
1:	vpcmpeqq (LRV_SIZE + XMM_SIZE)(%rsp), %xmm1, %xmm2
Packit 6c4009
	vpmovmskb %xmm2, %esi
Packit 6c4009
	cmpl $0xffff, %esi
Packit 6c4009
	jne 1f
Packit 6c4009
	VMOVA LRV_VECTOR1_OFFSET(%rsp), %VEC(1)
Packit 6c4009
Packit 6c4009
1:
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
# ifndef __ILP32__
Packit 6c4009
#  ifdef HAVE_MPX_SUPPORT
Packit 6c4009
	bndmov LRV_BND0_OFFSET(%rsp), %bnd0  # Restore bound registers.
Packit 6c4009
	bndmov LRV_BND1_OFFSET(%rsp), %bnd1
Packit 6c4009
#  else
Packit 6c4009
	.byte  0x66,0x0f,0x1a,0x84,0x24;.long (LRV_BND0_OFFSET)
Packit 6c4009
	.byte  0x66,0x0f,0x1a,0x8c,0x24;.long (LRV_BND1_OFFSET)
Packit 6c4009
#  endif
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
	fldt LRV_ST1_OFFSET(%rsp)
Packit 6c4009
	fldt LRV_ST0_OFFSET(%rsp)
Packit 6c4009
Packit 6c4009
	mov %RBX_LP, %RSP_LP
Packit 6c4009
	movq (%rsp), %rbx
Packit 6c4009
	cfi_restore(%rbx)
Packit 6c4009
	cfi_def_cfa_register(%rsp)
Packit 6c4009
Packit 6c4009
	add $48, %RSP_LP	# Adjust the stack to the return value
Packit 6c4009
				# (eats the reloc index and link_map)
Packit 6c4009
	cfi_adjust_cfa_offset(-48)
Packit 6c4009
	PRESERVE_BND_REGS_PREFIX
Packit 6c4009
	retq
Packit 6c4009
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size _dl_runtime_profile, .-_dl_runtime_profile
Packit 6c4009
#endif