|  | /* PLT trampolines.  i386 version. | 
|  | Copyright (C) 2004-2016 Free Software Foundation, Inc. | 
|  | This file is part of the GNU C Library. | 
|  |  | 
|  | The GNU C Library is free software; you can redistribute it and/or | 
|  | modify it under the terms of the GNU Lesser General Public | 
|  | License as published by the Free Software Foundation; either | 
|  | version 2.1 of the License, or (at your option) any later version. | 
|  |  | 
|  | The GNU C Library is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | Lesser General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU Lesser General Public | 
|  | License along with the GNU C Library; if not, see | 
|  | <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #include <sysdep.h> | 
|  | #include <link-defines.h> | 
|  |  | 
|  | #ifdef HAVE_MPX_SUPPORT | 
|  | # define PRESERVE_BND_REGS_PREFIX bnd | 
|  | #else | 
|  | # define PRESERVE_BND_REGS_PREFIX .byte 0xf2 | 
|  | #endif | 
|  |  | 
|  | .text | 
|  | .globl _dl_runtime_resolve | 
|  | .type _dl_runtime_resolve, @function | 
|  | cfi_startproc | 
|  | .align 16 | 
|  | _dl_runtime_resolve: | 
|  | cfi_adjust_cfa_offset (8) | 
|  | pushl %eax		# Preserve registers otherwise clobbered. | 
|  | cfi_adjust_cfa_offset (4) | 
|  | pushl %ecx | 
|  | cfi_adjust_cfa_offset (4) | 
|  | pushl %edx | 
|  | cfi_adjust_cfa_offset (4) | 
|  | movl 16(%esp), %edx	# Copy args pushed by PLT in register.  Note | 
|  | movl 12(%esp), %eax	# that `fixup' takes its parameters in regs. | 
|  | call _dl_fixup		# Call resolver. | 
|  | popl %edx		# Get register content back. | 
|  | cfi_adjust_cfa_offset (-4) | 
|  | movl (%esp), %ecx | 
|  | movl %eax, (%esp)	# Store the function address. | 
|  | movl 4(%esp), %eax | 
|  | ret $12			# Jump to function address. | 
|  | cfi_endproc | 
|  | .size _dl_runtime_resolve, .-_dl_runtime_resolve | 
|  |  | 
|  |  | 
|  | #ifndef PROF | 
|  | .globl _dl_runtime_profile | 
|  | .type _dl_runtime_profile, @function | 
|  | cfi_startproc | 
|  | .align 16 | 
|  | _dl_runtime_profile: | 
|  | cfi_adjust_cfa_offset (8) | 
|  | pushl %esp | 
|  | cfi_adjust_cfa_offset (4) | 
|  | addl $8, (%esp)		# Account for the pushed PLT data | 
|  | pushl %ebp | 
|  | cfi_adjust_cfa_offset (4) | 
|  | pushl %eax		# Preserve registers otherwise clobbered. | 
|  | cfi_adjust_cfa_offset (4) | 
|  | pushl %ecx | 
|  | cfi_adjust_cfa_offset (4) | 
|  | pushl %edx | 
|  | cfi_adjust_cfa_offset (4) | 
|  | movl %esp, %ecx | 
|  | subl $8, %esp | 
|  | cfi_adjust_cfa_offset (8) | 
|  | movl $-1, 4(%esp) | 
|  | leal 4(%esp), %edx | 
|  | movl %edx, (%esp) | 
|  | pushl %ecx		# Address of the register structure | 
|  | cfi_adjust_cfa_offset (4) | 
|  | movl 40(%esp), %ecx	# Load return address | 
|  | movl 36(%esp), %edx	# Copy args pushed by PLT in register.  Note | 
|  | movl 32(%esp), %eax	# that `fixup' takes its parameters in regs. | 
|  | call _dl_profile_fixup	# Call resolver. | 
|  | cfi_adjust_cfa_offset (-8) | 
|  | movl (%esp), %edx | 
|  | testl %edx, %edx | 
|  | jns 1f | 
|  | popl %edx | 
|  | cfi_adjust_cfa_offset (-4) | 
|  | popl %edx		# Get register content back. | 
|  | cfi_adjust_cfa_offset (-4) | 
|  | movl (%esp), %ecx | 
|  | movl %eax, (%esp)	# Store the function address. | 
|  | movl 4(%esp), %eax | 
|  | ret $20			# Jump to function address. | 
|  |  | 
|  | /* | 
|  | +32     return address | 
|  | +28     PLT1 | 
|  | +24     PLT2 | 
|  | +20     %esp | 
|  | +16     %ebp | 
|  | +12     %eax | 
|  | +8      %ecx | 
|  | +4      %edx | 
|  | %esp     free | 
|  | */ | 
|  | cfi_adjust_cfa_offset (8) | 
|  | 1:	movl %ebx, (%esp) | 
|  | cfi_rel_offset (ebx, 0) | 
|  | movl %edx, %ebx		# This is the frame buffer size | 
|  | pushl %edi | 
|  | cfi_adjust_cfa_offset (4) | 
|  | cfi_rel_offset (edi, 0) | 
|  | pushl %esi | 
|  | cfi_adjust_cfa_offset (4) | 
|  | cfi_rel_offset (esi, 0) | 
|  | leal 44(%esp), %esi | 
|  | movl %ebx, %ecx | 
|  | orl $4, %ebx		# Increase frame size if necessary to align | 
|  | # stack for the function call | 
|  | andl $~3, %ebx | 
|  | movl %esp, %edi | 
|  | subl %ebx, %edi | 
|  | movl %esp, %ebx | 
|  | cfi_def_cfa_register (ebx) | 
|  | movl %edi, %esp | 
|  | shrl $2, %ecx | 
|  | rep | 
|  | movsl | 
|  | movl (%ebx), %esi | 
|  | cfi_restore (esi) | 
|  | movl 4(%ebx), %edi | 
|  | cfi_restore (edi) | 
|  | /* | 
|  | %ebx+40  return address | 
|  | %ebx+36  PLT1 | 
|  | %ebx+32  PLT2 | 
|  | %ebx+28  %esp | 
|  | %ebx+24  %ebp | 
|  | %ebx+20  %eax | 
|  | %ebx+16  %ecx | 
|  | %ebx+12  %edx | 
|  | %ebx+8   %ebx | 
|  | %ebx+4   free | 
|  | %ebx     free | 
|  | %esp     copied stack frame | 
|  | */ | 
|  | movl %eax, (%ebx) | 
|  | movl 12(%ebx), %edx | 
|  | movl 16(%ebx), %ecx | 
|  | movl 20(%ebx), %eax | 
|  | call *(%ebx) | 
|  | movl %ebx, %esp | 
|  | cfi_def_cfa_register (esp) | 
|  | movl 8(%esp), %ebx | 
|  | cfi_restore (ebx) | 
|  | /* | 
|  | +40     return address | 
|  | +36     PLT1 | 
|  | +32     PLT2 | 
|  | +28     %esp | 
|  | +24     %ebp | 
|  | +20     %eax | 
|  | +16     %ecx | 
|  | +12     %edx | 
|  | +8      free | 
|  | +4      free | 
|  | %esp     free | 
|  | */ | 
|  | #if LONG_DOUBLE_SIZE != 12 | 
|  | # error "long double size must be 12 bytes" | 
|  | #endif | 
|  | # Allocate space for La_i86_retval and subtract 12 free bytes. | 
|  | subl $(LRV_SIZE - 12), %esp | 
|  | cfi_adjust_cfa_offset (LRV_SIZE - 12) | 
|  | movl %eax, LRV_EAX_OFFSET(%esp) | 
|  | movl %edx, LRV_EDX_OFFSET(%esp) | 
|  | fstpt LRV_ST0_OFFSET(%esp) | 
|  | fstpt LRV_ST1_OFFSET(%esp) | 
|  | #ifdef HAVE_MPX_SUPPORT | 
|  | bndmov %bnd0, LRV_BND0_OFFSET(%esp) | 
|  | bndmov %bnd1, LRV_BND1_OFFSET(%esp) | 
|  | #else | 
|  | .byte 0x66,0x0f,0x1b,0x44,0x24,LRV_BND0_OFFSET | 
|  | .byte 0x66,0x0f,0x1b,0x4c,0x24,LRV_BND1_OFFSET | 
|  | #endif | 
|  | pushl %esp | 
|  | cfi_adjust_cfa_offset (4) | 
|  | # Address of La_i86_regs area. | 
|  | leal (LRV_SIZE + 4)(%esp), %ecx | 
|  | # PLT2 | 
|  | movl (LRV_SIZE + 4 + LR_SIZE)(%esp), %eax | 
|  | # PLT1 | 
|  | movl (LRV_SIZE + 4 + LR_SIZE + 4)(%esp), %edx | 
|  | call _dl_call_pltexit | 
|  | movl LRV_EAX_OFFSET(%esp), %eax | 
|  | movl LRV_EDX_OFFSET(%esp), %edx | 
|  | fldt LRV_ST1_OFFSET(%esp) | 
|  | fldt LRV_ST0_OFFSET(%esp) | 
|  | #ifdef HAVE_MPX_SUPPORT | 
|  | bndmov LRV_BND0_OFFSET(%esp), %bnd0 | 
|  | bndmov LRV_BND1_OFFSET(%esp), %bnd1 | 
|  | #else | 
|  | .byte 0x66,0x0f,0x1a,0x44,0x24,LRV_BND0_OFFSET | 
|  | .byte 0x66,0x0f,0x1a,0x4c,0x24,LRV_BND1_OFFSET | 
|  | #endif | 
|  | # Restore stack before return. | 
|  | addl $(LRV_SIZE + 4 + LR_SIZE + 4), %esp | 
|  | cfi_adjust_cfa_offset (-(LRV_SIZE + 4 + LR_SIZE + 4)) | 
|  | PRESERVE_BND_REGS_PREFIX | 
|  | ret | 
|  | cfi_endproc | 
|  | .size _dl_runtime_profile, .-_dl_runtime_profile | 
|  | #endif |