/* PLT trampolines. ARM version. Copyright (C) 2005, 2010 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include #if defined(__USE_BX__) #define BX(x) bx x #else #define BX(x) mov pc, x #endif .text .globl _dl_runtime_resolve .type _dl_runtime_resolve, #function .cfi_sections .debug_frame cfi_startproc .align 2 _dl_runtime_resolve: cfi_adjust_cfa_offset (4) cfi_rel_offset (lr, 0) @ we get called with @ stack[0] contains the return address from this call @ ip contains &GOT[n+3] (pointer to function) @ lr points to &GOT[2] @ Save arguments. We save r4 to realign the stack. stmdb sp!,{r0-r4} cfi_adjust_cfa_offset (20) cfi_rel_offset (r0, 0) cfi_rel_offset (r1, 4) cfi_rel_offset (r2, 8) cfi_rel_offset (r3, 12) @ get pointer to linker struct ldr r0, [lr, #-4] @ prepare to call _dl_fixup() @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each sub r1, ip, lr sub r1, r1, #4 add r1, r1, r1 @ call fixup routine bl _dl_fixup @ save the return mov ip, r0 @ get arguments and return address back. We restore r4 @ only to realign the stack. ldmia sp!, {r0-r4,lr} cfi_adjust_cfa_offset (-24) @ jump to the newly found address BX(ip) cfi_endproc .size _dl_runtime_resolve, .-_dl_runtime_resolve #ifndef PROF .globl _dl_runtime_profile .type _dl_runtime_profile, #function .cfi_sections .debug_frame cfi_startproc .align 2 _dl_runtime_profile: cfi_adjust_cfa_offset (4) cfi_rel_offset (lr, 0) @ we get called with @ stack[0] contains the return address from this call @ ip contains &GOT[n+3] (pointer to function) @ lr points to &GOT[2] @ Stack layout: @ 212 - saved lr @ 208 - framesize returned from pltenter @ 16 - La_arm_regs @ 8 - Saved two arguments to _dl_profile_fixup @ 4 - Saved result of _dl_profile_fixup @ 0 - outgoing argument to _dl_profile_fixup @ For now, we only save the general purpose registers. sub sp, sp, #196 cfi_adjust_cfa_offset (196) stmia sp, {r0-r3} cfi_rel_offset (r0, 0) cfi_rel_offset (r1, 4) cfi_rel_offset (r2, 8) cfi_rel_offset (r3, 12) sub sp, sp, #16 cfi_adjust_cfa_offset (16) @ Save sp and lr. add r0, sp, #216 str r0, [sp, #32] ldr r2, [sp, #212] str r2, [sp, #36] @ get pointer to linker struct ldr r0, [lr, #-4] @ prepare to call _dl_profile_fixup() @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each sub r1, ip, lr sub r1, r1, #4 add r1, r1, r1 @ Save these two arguments for pltexit. add r3, sp, #8 stmia r3!, {r0,r1} @ Set up extra args for _dl_profile_fixup. @ r2 and r3 are already loaded. add ip, sp, #208 str ip, [sp, #0] @ call profiling fixup routine bl _dl_profile_fixup @ The address to call is now in r0. @ Check whether we're wrapping this function. ldr ip, [sp, #208] cmp ip, #0 bge 1f cfi_remember_state @ save the return mov ip, r0 @ get arguments and return address back add sp, sp, #16 cfi_adjust_cfa_offset (-16) ldmia sp, {r0-r3,sp,lr} cfi_adjust_cfa_offset (-200) @ jump to the newly found address BX(ip) cfi_restore_state 1: @ The new frame size is in ip. @ New stack layout: @ 268 - saved r7 @ 264 - saved result of _dl_profile_fixup @ 72 - La_arm_regs @ 64 - Saved two arguments to _dl_profile_fixup @ 0 - La_arm_retval @ For now, we only save the general purpose registers. @ Build the new frame. str r7, [sp, #212] cfi_rel_offset (r7, 212) sub r7, sp, #56 cfi_def_cfa_register (r7) cfi_adjust_cfa_offset (56) sub sp, sp, ip bic sp, sp, #7 @ Save the _dl_profile_fixup result around the call to memcpy. str r0, [r7, #264] @ Copy the stack arguments. mov r0, sp add r1, r7, #272 mov r2, ip bl memcpy @ Call the function. add ip, r7, #72 ldmia ip, {r0-r3} ldr ip, [r7, #264] mov lr, pc BX(ip) stmia r7, {r0-r3} @ Call pltexit. add ip, r7, #64 ldmia ip, {r0,r1} add r2, r7, #72 add r3, r7, #0 bl _dl_call_pltexit @ Return to caller. ldmia r7, {r0-r3} mov sp, r7 cfi_def_cfa_register (sp) ldr r7, [sp, #268] ldr lr, [sp, #92] add sp, sp, #272 cfi_adjust_cfa_offset (-272) BX(lr) cfi_endproc .size _dl_runtime_profile, .-_dl_runtime_profile #endif .previous